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
List
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
void main ()
{
INTVECTOR [20] = 50;
Vector
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
This statement creates an iterator for a Vector
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
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
#include
Using namespace std;
Double Darray [10] =
{1.0, 1.1, 1.6, 1.7, 1.8, 1.9};
Vector
int main ()
{
Vector
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
#include
#include
#include
Using namespace std;
Void Display (Vector
int main ()
{
// seed the random number generator
Srandom (Time (NULL));
// Construct Vector and Fill with Random Integer Values
Vector
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
{
COUT << Endl << S << endl;
Copy (v.begin (), v.end (),
ostream_iterator
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
The third parameter instantiates the ostream_iterator
$ 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
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
Vector
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
int main ()
{
List
// Copy IaRay Backwards INTO ILIST
Copy (IaRray, IARRAY 5, Front_Inserter (ILIST));
Display (ILIST, "Before Find and Copy);
// Locate Value 3 in ilist
List
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
{
Cout << s << endl;
Copy (A.BEGIN (), A.End (),
Ostream_iterator
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
List
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
#include
#include
#include
Vector
// 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
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
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
#include
#include
#define max 10
Vector
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 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 _Ty accumulate (_ii _f, _ii _l, _ty _v) {for (; _f! = _l; _ f) _V = _v * _f; Return (_V); // Template Function Accumulate with binop Template _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 #include #include #include #include Using namespace std; // Data to Randomize INT IARRAY [10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; Vector // Function Prototypes Void Display (Vector 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 { COUT << Endl << S << endl; Copy (vr.begin (), vr.end (), Ostream_Isterator 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 #include #include Using namespace std; // Data to Randomize INT IARRAY [10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; Vector // Function Prototype Void Display (Vector // 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 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 { COUT << Endl << S << endl; Copy (vr.begin (), vr.end (), Ostream_iterator Cout << Endl; } // Fiborand Class Constructionor Template 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 { 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 int main () { INT K = 0; COUNT_IF (alist.begin (), alist.end (), BIND1ST (Greater 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 This expression bundles greater 8> Q Q of the expression is an object in the container. Therefore, complete expressions COUNT_IF (alist.begin (), alist.end (), BIND1ST (Greater 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 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 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.