30 minutes to master STL

zhaozj2021-02-08  209

30 minutes to master STL

This is a small book. The original name is "Using STL", I don't know who is written. But I feel very interesting, I will translate it in two nights. I didn't check the contents of the translated content. If you can't feel gaining in 30 minutes, then throw it. I saved a lot of things in the text. Distressed, waste me two nights.

Translator: kary

Contact: karymay@163.net

STL overview

An important feature of STL is the separation of data structures and algorithms. Although this is a simple concept, this separation does make STL become very common. For example, since STL's sort () function is fully universal, you can use it to operate almost any data set, including linked lists, containers, and arrays.

Point

The STL algorithm is provided as a template function. In order to distinguish between the other components, the STL algorithm is coupled in this book, such as Sort ().

Another important feature of STL is that it is not object-oriented. In order to have enough versatility, STL mainly depends on the template instead of package, inheritance, and virtual function (polymorphism) - OOP. You can't find any obvious inheritance relationships in STL. This seems to be a reverse, but this is exactly a wide veneer of the STL's components. In addition, since the STL is a template, the use of the inline function makes the generated code short and efficient.

prompt

Make sure that at least -O optimization is used in compilation using the STL to ensure inline expansion.

STL component

STL provides a large number of templates and functions that can be used in OOP and regular programming. About 50 algorithms of all STL are fully common and do not rely on any specific data type. The following section describes three basic STL components:

1) The iterator provides a way to access objects in the container. For example, a pair of iterators can be used to specify certain ranges of objects in the List or VEC. The iterator is like a pointer. In fact, the C pointer is also an iterator. However, iterators can also be class objects that define Operator * () and other methods of operators similar to pointer.

2) The container is a data structure, such as List, Vector, and Deques, provided in a template class. In order to access the data in the container, it can be used by the iterator output from the container class.

3) The algorithm is a template function used to operate data in the container. For example, STL uses sort () to sort the data in a vector, search with the object in a list. The function itself has nothing to do with the structure and type of the data they operate, so they can be used on any data structure from a simple array to a highly complex container.

head File

To avoid conflicts with other header files, STL's header files no longer use conventional .h extensions. In order to include the standard String class, iterator and algorithm, with the following indicator:

#include

#include

#include

If you view the STL's header file, you can see the header file like Iterator.h and STL_ITerator.h. Since these names may differ between various STL implementations, you should avoid using these names to reference these headers. In order to ensure portability, the file name of the corresponding no .h suffix is ​​used. Table 1 lists the header files of the most commonly used containers. The table is incomplete, for other header files, I will introduce in this chapter and the next chapter.

Table 1. STL header files and container classes

#include

Container Class

Deque List Map, MultiMap Queue, priority_queue set, multiset stack vector, vector name space

Your compiler may not recognize the namespace. The name space seems to be an envelope, encapsulating the flag in another name. The logo is only existed in the namespace, thus avoiding conflicts with other markers. For example, there may be other libraries and program modules to define the sort () function, in order to avoid conflicts with the STL's sort () algorithm, SORT (), and other flags of STL are packaged in the namespace STD. STL's sort () algorithm compiles to std :: sort (), thereby avoiding the name conflict.

Although your compiler may not implement the namespace, you can still use them. In order to use STL, the following indicator can be inserted into your source code file, typically behind all #include indicators:

Using namespace std;

Iterator

The iterator provides an access method of an object in a container and defines the range of objects in the container. The iterator is like a pointer. In fact, the C pointer is also an iterator. However, iterator is not just a pointer, so you can't think they must have address values. For example, an array index may also be considered an iterator.

Iterator has a variety of different creative methods. The program may create an iterator as a variable. A STL container class may create an iterator in order to use a specific type of data. As a pointer, you must use the * Operator class to obtain data. You can also use other mathematical operators such as . Typical, operators are used to increment iterators to access the next object in the container. If the iterator reaches the back of the last element in the container, the iterator becomes a PAST-The-End value. Using a PAST-The-End is worth a pointer to access the object is illegal, it seems that it is just like a NULL or the initialized pointer.

prompt

STL does not guarantee an iterator from another iterator. For example, when you are sorted in a collection, if you specify two iterators in different structures, the second iterator cannot arrive from the first iterator, at which time the program is destined to fail. This is a price of STL flexibility. STL does not guarantee unreasonable errors.

Iterator type

For STL data structures and algorithms, you can use five iterators. The following is a brief explanation of these five types:

· Input Iterators provide read-only access to data.

· Output Iterators provides only access to data

· Forward Iterators provides read and write operations and advances the iterator forward.

· Bidirectional Iterators provides read and write operations and can operate forward and backward.

· Random Access Iterators provides read and write operations and can be randomly moved in the data.

Although the details of different STL implementations are different, it is still possible to imagine the above inheritance relationship. In this sense, the following iterator inherits the iterator from the top. Due to this inheritance relationship, you can use a Forward iterator as an Output or Input iterator. Similarly, if an algorithm requires a bidirectional iterator, you can only use this type and random access iterator.

Pointer iterator

As shown below, a pointer is also an iterator. The program also shows a main feature of the STL - it is not only available for its own class type, and can also be used for any C or C type. Listing 1, iterdemo.cpp, showing how to use the pointer as an iterator for the STL's Find () algorithm to search for a normal array. Table 1. IterDemo.cpp

#include

#include

Using namespace std;

#define size 100

INT IARRAY [SIZE];

int main ()

{

IARRAY [20] = 50;

INT * IP = Find (IAARRAY, IARRAY SIZE, 50);

IF (ip == aaray size)

COUT << "50 not found in array" << endl;

Else

Cout << * IP << "Found in Array" << Endl;

Return 0;

}

The program tells the compiler to use the STD namespace using the STD name space. This line using STD namespace is optional because it can be deleted that this line will not cause the name conflict.

The overall number of sizes is defined in the program. Since it is a global variable, the runtime array automatically initials to zero. The following statement will set to 50 at the index 20 position, and use the find () algorithm to search for value 50:

IARRAY [20] = 50;

INT * IP = Find (IAARRAY, IARRAY SIZE, 50);

The Find () function accepts three parameters. The first two define the scope of the search. Because the C and C arrays are equivalent to the pointers, the expression IARRAY points to the first element of the array. The second parameter IARRAY size is equivalent to the last-the-End value, which is the back position of the last element in the array. The third parameter is the value to be positioned, that is, 50. The Find () function returns the same type of iterator as the first two parameters, which is a pointer IP pointing to integers.

prompt

You must remember that STL uses templates. Therefore, the STL function automatically constructs according to the data type they use.

In order to determine if the Find () is successful, the IP and PAST-the-End value are tested in the example:

IF (ip == aaray size) ...

If the expression is true, it is indicated that there is no specified value in the range of the search. Otherwise, point to a legal object's pointer, then display ::

Cout << * IP << "Found in Array" << Endl;

The test function returns and NULL is incorrect. Don't use it below:

INT * IP = Find (IAARRAY, IARRAY SIZE, 50);

IF (ip! = null) ... // ??? incorrect

When using the STL function, can only test whether the IP is equal to whether the PAST-the-End value is equal. Although IP in this example is a C pointer, the usage must also comply with the rules of the STL iterator.

Container iterator

Although the C pointer is also an iterator, more is the container iterator. The container iterator usage is the same as IterDemo.cpp, but the iterator is declared that the pointer variable is different, you can use the container class method to get an iterator object. Two typical container methods are begin () and end (). They represent the entire container range in most containers. Some other containers also provide reverse iterators using Rbegin () and rend () methods to specify the range of objects in the reverse order. The following program creates a vector container (STL and array equivalent object) and searches for it using iterators. The program is the same as the program in the previous chapter.

Listing 2. vectDemo.cpp

#include

#include

#include

Using namespace std;

Vector intVector (100);

void main ()

{

INTVECTOR [20] = 50;

Vector :: item INTITER =

Find (intVector.begin (), intVector.end (), 50);

IF (INTITER! = intVector.end ())

COUT << "Vector Contains Value" << * intiter << Endl;

Else

COUT << "Vector does not contain 50 << endl;

}

Note Use the following method to display the search data:

COUT << "Vector Contains Value" << * intiter << Endl;

Constant iterator

Like the pointer, you can assign an iterator. For example, first stipulating an iterator:

Vector :: item first;

This statement creates an iterator for a Vector class. The following statement sets the iterator to the first object of the intVector and sets the object value it points to 123 ::

FigSt = intVector.begin ();

* first = 123;

This assignment is allowed for most containers, except for read-only variables. In order to prevent the error, it can be applied to the iterator:

Const vector :: item result;

Result = find (intVector.begin (), intVector.end (), value);

IF (Result! = intVector.end ())

* Result = 123; //???

caveat

Another kind of prevention of data is changed to decrease the container as a Const type.

"Yeah!" In the VC, the correct meaning is that the correct meaning is that the object is constant instead of whether it points to the object is not allowed, like int * const p; it seems that this author does not understand

Use iterator programming

You have seen some examples of iterators, and now we will pay attention to how each particular iterator is used. Since the use iterator requires knowledge about STL container classes and algorithms, you may need to retrieve this chapter after reading the following two chapters.

Enter an iterator

The input iterator is the most common type. The input iterator can be used at least == and! = Testing, etc.; use * to access data; use operation to recruit iterators to the next element or reach the PAST-the-End value.

In order to understand how iterator and STL functions use them, now take a look at the definition of the Find () template function: Template

InputItemrator Find

InputITerator First, InputITerator Last, Const T & Value) {

While (First! = Last && * first! = value) first;

Return first;

}

note

In the Find () algorithm, note if first and last point to different containers, the algorithm may fall into a dead cycle.

Output iterator

The output iterator default is written only, usually used to copy data from one location to another. Since the output iterator cannot read objects, you will not use it in any search and other algorithms. To read a copy value, you must use another input iterator (or its inheritance iterator).

Listing 3. Outiter.cpp

#include

#include // NEED COPY ()

#include // NEED VECTOR

Using namespace std;

Double Darray [10] =

{1.0, 1.1, 1.6, 1.7, 1.8, 1.9};

Vector vdouble (10);

int main ()

{

Vector :: item outputiterator = vdouble.begin ();

Copy (Darray, Darray 10, Outputiterator);

While (Outputiterator! = vdouble.end ()) {

Cout << * Outputiterator << Endl;

Outputiterator ;

}

Return 0;

}

note

When using a copy () algorithm, you must ensure that the target container has a large space, or the container itself is automatically expanded.

Proderation

The prior to the yourself can read and write data values ​​and can advance to the next value. But it can't be decremented. The replace () algorithm shows the usage method of the prior gemold.

Template

Void Replace (ForwardItemator First,

ForwardItemrator Last,

Const T & Old_Value,

Const t & new_value;

Replace all values ​​in [First, Last] with Replace () Replace all values ​​of [FIRST, LAST] to NEW_VALUE. :

Replace (vdouble.begin (), vdouble.end (), 1.5, 3.14159);

Two-way iterator

Two-way iterator requirements can be increased or decrease. If the Reverse () algorithm requires two two-way iterators as parameters:

Template

Void Reverse (BidirectionAliterator First,

BidirectionAliterator Last);

Use the Reverse () function to reverse the container in reverse:

Reverse (vdouble.begin (), vdouble.end ());

Random access iterator

Random access iterators can access data in any order and can be used to read and write data (not C pointers that Const) are also random access iter). STL sorting and search functions use random access iterators. Random access iterators can use the relationship operation comparison. The random_shuffle () function randomly disrupts the original order. Declared as:

Template

Void random_shuffle (RandomaccessItemrator First,

RandomaccessITerator Last;

Instructions:

Random_shuffle (vdouble.begin (), vdouble.end ());

Iterator technology

To learn to use iterators and containers and algorithms, you need to learn the following new technologies.

Stream and iterator

Many examples of this book use I / O state of statements to read and write data. E.g:

Int value;

Cout << "Enter Value:";

CIN >> VALUE;

Cout << "you entered" << value << endl;

For iterators, there is another method to use flow and standard functions. The point of understanding is to treat the input / output stream as a container. Therefore, any algorithm that accepts iterator parameters can work with the stream.

Listing 4. Outstrm.cpp

#include

#include // need random (), Srandom ()

#include // NEED TIME ()

#include // NEED SORT (), COPY ()

#include // NEED VECTOR

Using namespace std;

Void Display (Vector & V, Const Char * S);

int main ()

{

// seed the random number generator

Srandom (Time (NULL));

// Construct Vector and Fill with Random Integer Values

Vector Collection (10);

For (int i = 0; i <10; i )

Collection [i] = random ()% 10000 ;;

// Display, sort, and redisplay

Display (Collection, "Before Sorting");

Sort (Collection.Begin (), Collection.end ());

Display (Collection, "After Sorting");

Return 0;

}

// Display Label S and Contents of Integer Vector V

Void Display (Vector & V, Const Char * S)

{

COUT << Endl << S << endl;

Copy (v.begin (), v.end (),

ostream_iterator (cout, "/ t"));

Cout << Endl;

}

The function display () shows how to use an output stream for yourself. The following statement transmits the value in the container to the COUT output stream object:

Copy (v.begin (), v.end (), ostream_iterator (cout, "/ t"));

The third parameter instantiates the ostream_iterator type and uses it as the output target iterator object of the COPY () function. The "/ t" string is a separator. operation result:

$ G Outstrm.cpp

$ ./a.out

BEFORE SORTING

677 722 686 238 964 397 251 118 11 312

After sorting

11 118 238 251 312 397 677 686 722 964

This is the magical side of the STL "indeed magical". To define the output flow, STL provides template class OSTREAM_ITERATOR. This class's constructor has two parameters: an Ostream object and a string value. Therefore, you can create an iterator object as simply as follows:

Ostream_Iterator (cout, "/ n")

This iteration can be used with any function that accepts an output iterator.

Insert iterator

Insert iterators are used to insert values ​​into the container. They are also called an adapter because they adapt to a container or converted into an iterator and is used in the algorithm such as copy (). For example, a program defines a linked list and a vector container:

List dlist;

Vector DVector;

By using the Front_Inserter iterator object, you can complete the object inserting the object into the front end of the chain table with only a single copy () statement:

Copy (DVector.Begin (), DVector.end (), Front_Inserter (DLIST));

The three insert iterators are as follows:

• The normal insert is inserted into the front of any object of the container.

· Front INSERTERS inserts the object to the front of the dataset - for example, the linked list header.

· Back INSERTERS is inserted into the tail of the collection - for example, the tail of the vector, causing the vector container extension.

Using an inserting iterator may cause other objects in the container to move positions, thus makes existing iterators illegally. For example, inserting an object into the vector container will cause other values ​​to move the position to make a space. In general, it is more effective in inserting an icon list because they do not cause other objects to move.

Listing 5. INSERT.CPP

#include

#include

#include

Using namespace std;

INT IARRAY [5] = {1, 2, 3, 4, 5};

Void Display (List & v, const char * s);

int main ()

{

List ilist;

// Copy IaRay Backwards INTO ILIST

Copy (IaRray, IARRAY 5, Front_Inserter (ILIST));

Display (ILIST, "Before Find and Copy);

// Locate Value 3 in ilist

List :: Iterator P =

IList.egin (), IList.end (), 3);

// Copy First Two IaRray Values ​​To ilist Ahead of P

Copy (IaRray, IaRray 2, INSERTER (ILIST, P)); Display (ILIST, "After Find and Copy);

Return 0;

}

Void Display (List & a, const char * s)

{

Cout << s << endl;

Copy (A.BEGIN (), A.End (),

Ostream_iterator (cout, "));

Cout << Endl;

}

The results of the operation are as follows:

$ G insert.cpp

$ ./a.out

Before Find and Copy

5 4 3 2 1

After Find and Copy

5 4 1 2 3 2 1

You can replace Front_Insert to try back_inserter.

If you use Find () to find a value that does not exist in the list, for example, 99. Since Past-the-end value is set at this time. The final copy () function attached the value of the IARRAY to the rear of the linked list.

Mix iterator function

In operation involving containers and algorithms, there are also two iterator functions:

· Advance () Adds or decreases iterators as specified.

· Distance () Returns the number of operations required to reach an iterator (increment) operation.

E.g:

List ilist;

List :: Iterator P =

IList.egin (), IList.end (), 2);

COUT << "Before: p ==" << * P << endl;

Advance (p, 2); // Same AS P = P 2;

Cout << "after: p ==" << * p << endl;

INT K = 0;

Distance (p, ilist.end (), k);

Cout << "k ==" << k << Endl;

The Advance () function accepts two parameters. The second parameter is the number of advanced advancement. For the front gear, this value must be positive, and the value can be negative for the two-way iterator and the random access iterator.

Use the discance () function to return to the steps you need to reach another iterator.

note

The distance () function is iterative, that is, it increments the third parameter. Therefore, you must initialize this parameter. This parameter is not initialized to fail.

Function and function object

In STL, the function is called an algorithm, which is more common compared to the standard C library function. The STL algorithm is implemented as a template class or template function by overloading the Operator () function. These classes are used to create a function object, perform a wide variety of operations in the container. The following sections explain how to use functions and function objects.

Function and assertion

It is often necessary to perform user-defined operations in the container. For example, you might want to traverse all objects of all objects in a container can call our function. E.g

#include

#include // need random (), Srandom ()

#include // NEED TIME ()

#include // NEED VECTOR

#include // NEED for_each () # define vsize 24 // size of multi

Vector v (vsize); // vector object Object

// Function Prototypes

Void Initialize (long & ri);

Void Show (Const long & ri);

Bool Isminus (Const Long & Ri); // Predicate Function

int main ()

{

Srand (Time (NULL)); // seed random generator

For_each (v.begin (), v.end (), initialize; // call normal functions

COUT << "Vector of Signed Long Integers" << Endl;

For_each (v.begin (), v.end (), show);

Cout << Endl;

// use predicate function to count negative values

//

INT count = 0;

Vector :: items P;

P = find_if (v.begin (), v.end (), isminus); // call the assertion function

While (p! = v.end ()) {

COUNT ;

P = find_if (p 1, v.end (), isminus);

}

Cout << "Number of Values:" << vsize << Endl;

Cout << "Negative Values:" << count << Endl;

Return 0;

}

// set ri to a signed integer value

Void Initialize (long & ri)

{

Ri = (randM () - (rand_max / 2));

// ri = random ();

}

// Display Value of Ri

Void Show (Const long & ri)

{

COUT << ri << "

}

// Returns True if ri is Less Than 0

Bool Isminus (Const long & ri)

{

Return (Ri <0);

}

The so-called assertory function is a function that returns the BOOL value.

Function object

In addition to passing a callback function to the STL algorithm, you may also need to pass a class object to perform more complex operations. Such an object is called a function object. In fact, the function object is a class, but it can be called with the callback function. For example, statistics can be retained each time the function object is called by the for_each () or FIND_IF () function. Function objects are implemented by overloading Operator () () (). If TanyClass defines Opeator () (), you can use it:

Tanyclass Object; // Construct Object; // Construct Object; // Construct Object; // Construct Object;

Object (); // Calls TanyClass :: Operator () () FUNCTION

For_each (v.begin (), v.end (), object);

STL defines several functions. Since they are templates, they can be used for any type, including the intrinsic data type inherent in C / C , such as long. Some function objects can see its use from the name, such as Plus () and multiplies (). Similar greater () and less-equal () are used to compare two values. note

Some versions of ANSI C define the Times () function object, while GNU C names it Multiplies (). The header file must be included when using it.

An application of a useful function object is an Accumulate () algorithm. This function calculates the sum of all values ​​in the container. Remember that such a value is not necessarily a simple type, by overloading Operator () or class object.

Listing 8. Accum.cpp

#include

#include // NEED Acumulate ()

#include // NEED VECTOR

#include // NEED MULTIPLIES () (or Times ())

#define max 10

Vector v (max); // Vector Object

int main ()

{

// Fill Vector Using Conventional Loop

//

For (int i = 0; i

v [i] = i 1;

// Accumulate The Sum of Contained VALUES

//

Long Sum =

Accumulate (v.begin (), v.end (), 0);

COUT << "SUM OF VALUES ==" << Sum << endl;

// Accumulate The Product of Contained Values

//

Long product =

Accumulate (v.begin (), v.end (), 1, multiplies ()); // pay attention to this line

COUT << "Product of Values ​​==" << Product << Endl;

Return 0;

}

The compilation output is as follows:

$ G Accum.cpp

$ ./a.out

Sum of values ​​== 55

Product of values ​​== 3628800

"Note Usage of AccuLate () using a function object. Accumulate () Calculate the objects of the objects and the third parameter in each container as the parameters of the Multiplies function object, Multiplies (1, v). The source code of these templates in the VC is as follows:

// Template Function Accumulate

Template inline

_Ty accumulate (_ii _f, _ii _l, _ty _v)

{for (; _f! = _l; _ f)

_V = _v * _f;

Return (_V);

// Template Function Accumulate with binop

Template inline

_Ty accumulate (_ii _f, _ii _l, _ty _v, _bop _b) {for (; _f! = _L; _ f)

_V = _b (_v, * _f);

Return (_V);

// Template struct binary_function

Template

Struct binary_function {

TYPEDEF _A1 First_Argument_type;

TYPEDEF _A2 SECOND_ARGUMENT_TYPE;

Typedef _r result_type;

}

// Template struct multiplies

Template

Struct Multiplies: binary_function <_ty, _ty, _ty> {

_Ty operator () (const _ty & _x, const _ty & _y) const

{return (_x * _y);}

}

Introduction: If you want to know how STL is implemented, the best way is to write a simple program, put the template source code involved in the program to COPY, slightly finish, you can understand. So there is no need to buy a book such as "STL source profiling", and those books may waste time. "

Generator function object

There is a class of useful function objects being "generator". Such functions have their own memory, that is, it can remember a value from the previous call. For example, a random number generator function.

Ordinary C programmers use static or global variables "Memory" last call results. But the disadvantage of this is that the function cannot be separated from its data. "There is also a disadvantage to use TLS to thread security." Obviously, use classes to encapsulate a piece: "Memory" is safer and reliable. Let's take a look at the example:

Listing 9. randfunc.cpp

#include

#include // need random (), Srandom ()

#include // NEED TIME ()

#include // need random_shuffle ()

#include // NEED VECTOR

#include // NEED PTR_FUN ()

Using namespace std;

// Data to Randomize

INT IARRAY [10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};

Vector v (IARRAY, IARRAY 10);

// Function Prototypes

Void Display (Vector & VR, Const Char * S);

Unsigned int RANDINT (const unsigned int n);

int main ()

{

Srand (Time (NULL)); // seed random generator

Display (v, "before shuffle:");

Pointer_to_unary_function

PTR_RAndint = PTR_FUN (Randint); // Pointer to Randint () // Note this line

Random_shuffle (v.begin (), v.end (), ptr_randin; display (v, "after shuffle:");

Return 0;

}

// Display Contents of Vector VR

Void Display (Vector & VR, Const Char * S)

{

COUT << Endl << S << endl;

Copy (vr.begin (), vr.end (), Ostream_Isterator (cout, "));

Cout << Endl;

}

// Return next Random Value in Sequence MODULO N

Unsigned int RANDINT (const unsigned int N)

{

Return random ()% n;

}

The compilation operation is as follows:

$ G randfunc.cpp

$ ./a.out

BEFORE SHUFFLE:

1 2 3 4 5 6 7 8 9 10

After shuffle:

6 7 2 8 3 5 10 1 9 4

First, use the following statement to declare an object:

Pointer_to_unary_function

PTR_RAndint = PTR_FUN (Randint);

This uses STL's single-grade function template to define a variable PTR_Randint, and initialize the address to our function randint (). A single-grade function accepts a parameter and returns a value. Now Random_shuffle () can be called as follows:

Random_shuffle (v.begin (), v.end (), ptr_randint);

In this example, the generator is just a simple calls the RAND () function.

A little hassle about constant quotes (not translated, VC will be removed under the example)

Generator function class object

The following example shows the use of generator function class objects.

Listing 10. Fiborand.cpp

#include

#include // need random_shuffle ()

#include // NEED VECTOR

#include // NEED UNARY_FUNCTION

Using namespace std;

// Data to Randomize

INT IARRAY [10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};

Vector v (IARRAY, IARRAY 10);

// Function Prototype

Void Display (Vector & VR, Const Char * S);

// The Fiborand Template Function-Object Class

Template

Class Fiborand: Public Unary_Function {

INT I, J;

Arg sequence [18];

PUBLIC:

Fiborand ();

Arg Operator () (Const Arg & Arg);

}

void main ()

{

FIBORAND Fibogen; // Construct Generator Object

Cout << "Fibonacci Random Number Generator" << ENDL;

Cout << "Using Random_shuffle and a function object" << Endl;

Display (v, "before shuffle:");

Random_shuffle (v.begin (), v.end (), fibogen;

Display (V, "After shuffle:");

}

// Display Contents of Vector VR

Void Display (Vector & VR, Const Char * S)

{

COUT << Endl << S << endl;

Copy (vr.begin (), vr.end (),

Ostream_iterator (cout, "));

Cout << Endl;

}

// Fiborand Class Constructionor

Template

FIBORAND :: fiborand ()

{

SEQUENCE [17] = 1;

SEQUENCE [16] = 2;

For (int N = 15; n> 0; N-)

Sequence [N] = SEQUENCE [N 1] Sequence [n 2];

i = 17;

J = 5;

}

// Fiborand Class Function Operator

Template

Arg Fiborand :: Operator () (const arg & arg)

{

Arg K = SEQUENCE [I] sequence [j];

Sequence [i] = K;

I-;

J -;

IF (i == 0) i = 17;

IF (j == 0) j = 17;

Return K% arg;

}

The compilation operation is as follows:

$ G Fiborand.cpp

$ ./a.out

Fibonacci Random Number Generator

USING RANDOM_SHUFFLE AND A FUNCTION OBJECT

BEFORE SHUFFLE:

1 2 3 4 5 6 7 8 9 10

After shuffle:

6 8 5 4 3 7 10 1 9

This program uses rand_shuffle with a completely unreasonable method. The Fibonacci generator package is in a class, which can remember the results from previous "use". In this example, class FIBORAND maintains an array and two index variables I and J.

FIBORAND class inherits from the unary_function () template:

Template

Class Fiborand: public unary_function {...

ARG is a user-defined data type. This class also sets two member functions, one is a constructor, and the other is an Operator () () function that allows the Random_shuffle () algorithm as "call" a Fiborand object like a function.

Binder function object

A binding uses another function object F () and the parameter value V creates a function object. The bound function object must be a binocular function, that is, there are two parameters, A and B. STLs are: • Bind1st () Create a function object that will value the value V as the first parameter A.

· BIND2ND () Creates a function object that will value Value V as the second parameter B.

For example, as follows:

Listing 11. Binder.cpp

#include

#include

#include

#include

Using namespace std;

// data

INT IARRAY [10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};

List Alist (IARRAY, IARRAY 10);

int main ()

{

INT K = 0;

COUNT_IF (alist.begin (), alist.end (),

BIND1ST (Greater (), 8), k);

COUT << "Number Elements <8 ==" << k << endl;

Return 0;

}

Algorithm count_if () calculates the number of elements that meet specific conditions. This is implemented by bundling a function object and a parameter into an object, and the object is implemented as the third parameter of the algorithm. Pay attention to this expression:

BIND1ST (Greater (), 8)

This expression bundles greater () and a parameter value 8 into a function object. Since bind1st () is used, the function is equivalent to calculating the following expression:

8> Q

Q of the expression is an object in the container. Therefore, complete expressions

COUNT_IF (alist.begin (), alist.end (),

BIND1ST (Greater (), 8), k);

Calculate the number of objects that are less than or equal to 8.

Negative function object

The so-called negative function object is created from another function object. If the original function returns true, the negative function object returns a false. There are two negative functions: NOT1 () and NOT2 (). NOT1 () accepts a single-optical function object, and NOT2 () accepts binocular functions. Negative function objects are usually used with a gear. For example, use bind1nd to search for Q <= 8 in the last section:

COUNT_IF (alist.begin (), alist.end (),

BIND1ST (Greater (), 8), k);

If you want to search for q> 8 objects, use bind2st. And now you can write this:

START = FIND_IF (alist.begin (), alist.end (),

NOT1 (Bind1nd (Greater (), 6)))

You must use NOT1 because bind1nd returns a single-graphic function.

Summary: Use Standard Template Library (STL)

Although many programmers are still using standard C functions, this is like riding a Mercedes to find mercedes. Of course, it will eventually reach the target, but you waste a lot of time.

Although it is sometimes convenient to use standard C functions (such as using sprintf () to format the output). However, the C function does not use an exception mechanism to report an error, nor is it suitable for processing a new data type. Moreover, the standard C function often uses memory allocation technology, and there is no experience, which is easy to write BUG. .

The C standard library provides more secure, more flexible data set processing. STL was originally developed by Alexander Stepanov and Meng Lee in the HP Lab. Recently, the C Standards Committee adopted STL, although there is still a detail between different implementations. The two most important features of STL: the separation of data structure and algorithm, non-objective nature. The access object is implemented by the same iterator like a pointer; the container is the data structure of the linked list, the vector, and is provided in a template; the algorithm is a function template for operation of the data in the container. Since STL is based on a template, it can be used for any data type and structure.

转载请注明原文地址:https://www.9cbs.com/read-3054.html

New Post(0)