STL sequential container (array, vector, deque, list) learning summary

Containers and Iterators

What is container ?

A container , simply understood, is a collection of template classes , which encapsulates data structures (such as stacks, queues, hash tables , etc., which we are familiar with).

STL provides three standard containers:

  1. Sequence container : The position of the element in the container is independent of the value of the element ( unordered ), such as vector vector container, list list container and deque double-ended queue container.
  2. Sorting container : The elements in the sorting container are sorted ( ordered ) from small to large by default . Even if an element is inserted, the element will be inserted into the appropriate position. Such as set collection container and map mapping container.
  3. Hash container : The elements in a hash container are unsorted and the position of the elements is determined by the hash function.

What is iterator ?

Iterators are the inevitable result of the development of generic technology. We often need to traverse the elements in the container. Although the internal structures of different containers have their own characteristics, they are essentially used to store large amounts of data. The storage unit of the string is composed of the storage unit, so the operation method of traversal is similar, so the iterator appears, so that the container and the algorithm can be separated to realize the access to the data.

The iterator can be of any type required, and it can point to an element in the container, or perform read/write operations on the element.

Iterators are divided into input iterators, output iterators, forward iterators, bidirectional iterators, and random access iterators according to their functions .

  1. Input and output iterators : The objects of operation are input/output streams.
  2. Forward iterator : p is a forward iterator, then p supports ++p, p++, *p operations, can also be copied or assigned, and can be compared with == and != operators. Additionally, two forward iterators can assign values ​​to each other.
  3. Bidirectional iterators : On the basis of forward iterators, bidirectional iterators also support -p or p- operations.
  4. Random Access Iterator : Has the full functionality of a bidirectional iterator (the most powerful!) and has unique operations: as follows
    • p+=i: Make p move i elements backward.
    • p-=i: Make p move forward i elements.
    • p+i: Returns an iterator of the ith element after p.
    • pi: Returns an iterator of the ith element preceding p.
    • p[i]: Returns a reference to the i-th element after p.
    • Comparisons can be made using the <, >, <=, >= operators
    • Support p2-p1 (returns the difference between the sequence numbers of the element pointed to by p2 and the element pointed to by p1)

Different types of iterators are specified for use in different containers.

containerCorresponding iterator type
arrayrandom
vectorrandom
dequerandom
listtwo-way
set / multisettwo-way
map / multimaptwo-way
forward_listforward
unordered_map / unordered_multimapforward
unordered_set / unordered_multisetforward
stacknot support
queuenot support

Simple use of iterators

We traverse the vector container using an iterator:

# include <iostream>
 # include <vector>

using  namespace std ;

int  main ( ) 
{ 
    vector < char > hello { 'h' , 'e' , 'l' , 'l' , 'o' , '!' } ; //Initialize a vector container and initialize the contents of the container elements, vector The corresponding iterator type is the random access iterator 
    cout << "method one:" << endl ; 
    for  ( int i =  0 ; i < hello . size ( ) ;i ++ ) //Call the size() method of the container to get the container size 
    {
        cout << hello [ i ] ; 
    } 
    cout << endl ;
    
    cout << "method two:" << endl ; 
    vector < char > :: iterator iter ; //define a forward iterator iter to vector<char> 
    for  ( iter = hello . begin ( ) ; iter != hello .end ( ) ; iter ++ ) //Use the ! = operator to compare whether two iterators are equal, and also show that iterators can be assigned to each other { 
        cout << * iter ; // *Iterator name means accessing the iterator pointed to element of } 
    cout << endl
     
    ;

    cout << "method three:" << endl ; 
    iter = hello . begin ( ) ; 
    while  ( iter < hello . end ( ) ) //Iterators can use the < operator to compare sizes 
    { 
        cout << * iter ; 
        iter = iter + 2 ;  //The iterator moves backward 2 elements each time 
    } 
    cout << endl ;

    getchar ( ) ; 
    return  0 ; 
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35

Output result:

method one:
hello!
method two:
hello!
method three:
hlo
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

Basic operations of iterators

definition

Although different containers correspond to different types of iterators, these iterators have a relatively uniform definition, which can be divided into four types:

  1. Forward iterator :container class name::iterator iterator name;
  2. Constant forward iterator :container class name::const_iterator iterator name;
  3. Reverse iterator :container class name::reverse_iterator iterator name;
  4. Constant reverse iterator :container class name::const_reverse_iterator iterator name;

Note: The above 4 ways of defining iterators are not applicable to every container. Some containers support the above four methods at the same time, such asarray, deque, vector; and some containers only support some of these definitions, such asforward_listContainers only support the definition of forward iterators, not reverse iterators.

In the above program, we define a forward iterator of vector type:vector<char>::iterator iter;

access element

pass through* iterator nameRepresents access to the element pointed to by the iterator

Modify the iterator to point to

Iterators can be modified to point to elements by ++, –, +=, -=, etc. But there is a difference between one-way iterators and reverse iterators:

  • When the ++ operation is performed on the forward iterator, the iterator points to the next element
  • When the reverse iterator performs the ++ operation, the iterator points to the previous element
Other considerations
  • Bidirectional iterators cannot compare sizes, random iterators can compare sizes
  • Input iterators are used to read in data, and output iterators are used to write data
  • stack and queue are container adapters and cannot use iterators

The following procedure:

# include <iostream>
 # include <list>
 using  namespace std ; 
int  main ( ) 
{ 
    list < int > l { 1 , 2 , 3 , 4 , 5 , 6 , 7 } ; 
    list < int > :: iterator iter ; 
    for ( iter = l.begin ( ) ;   iter _ _!=   l . end ( ) ; iter ++ ) { 
        cout << * iter ; 
    } 
    for  ( iter = l . begin ( ) ; iter < l . end ( ) ; iter ++ ) //! Note that an error will be reported! Because list<int> is a bidirectional iterator, you cannot use < to compare 
    { 
        cout << * iter ; 
    } 
    getchar ( ) ; 
    return  0 ;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

Above we defined a list container, note that the list container is a bidirectional iterator. And we created another forward iterator. We can use != to compare these two iterators, but not < because bidirectional iterators do not support < comparisons.

Therefore, try to usefor(itr = l.begin(); itr != l.end(); itr++), instead offor(itr = l.begin(); itr < l.end(); itr++)Because the former is common to all kinds of iterators, the latter is only common to random iterators , and once you consider traversing from back to front, you need to change "<"to">".

serial container

A sequential container is an unordered container that stores a specified type of storage in a linear arrangement, which can storeint,doubleand other types of data.

The following T represents the type (Type), and N represents the number (Numbers)

Sequence containers include the following categories:

  • array<T,N>: Array container, defined to store N elements of type T, with a fixed length.
  • vector<T>: vector container, variable length (that is, more memory space can be applied when the space is insufficient)
  • list<T>: linked list container (doubly linked list), variable length, fast adding/deleting elements, slow accessing elements.
  • deque<T>: Deque, variable length, efficient to add or remove elements at the head and tail, but slower elsewhere.
  • forward_list<T>: Forward linked list container (single linked list), saves memory but is more efficient thanlistlower.

array<T,N>Array container

head File:#include<array>

Features : The size is fixed and cannot be dynamically expanded.

create an array

Suppose we want to create an array container my_array that contains 10 double types, as follows:

std :: array < double , 10 > my_array ;
  • 1

The need to add std:: is because it is under the std namespace, and it should be noted that the initialized N size of the array container must be a constant , not a variable.

We can also initialize the array container when we create it, just as we would initialize a regular array:

std :: array < double , 10 > my_array { 2.5 , 4 , 5.9 , 0.8 } ;
  • 1

If no initialization value is specified, it defaults to 0 or a value equivalent to '0' for the element type:

std :: array < double , 10 > my_array { } ;		
  • 1

array member function

Array has many member functions, begin(), end(), size(), etc., etc., you can go to thehttp://www.cplusplus.com/reference/stl/Find out.

Below we use an example to briefly introduce the role of member functions:

# include <iostream>
 # include <array>
 using  namespace std ;

int  main ( ) 
{ 
    array < double , 10 > my_array { 4 , 0.4 , 8.2 , 5.3 , 8.9 , 0.4 , 9.9 , 100.3 } ; //Initialization defaults to all 0s

    if  ( my_array . empty ( ) ) //empty() function: judging whether the container is empty, it has the same function as the judging condition through size()==0, but its efficiency may be faster. 
    { 
        cout << "array is empty!" << endl ; 
    } else 
    { 
        cout << "array is not empty!" << endl ; 
    }

    array < double , 10 > :: iterator iter ; 
    for   ( iter = my_array . begin ( ) ; iter !=   my_array . end ( ) ; iter ++ ) // traverse through iterator 
    { //begin(): return pointer to container A random access iterator for the first element in 
     //end(): returns a random access iterator to a position after the last element of the container 
        cout << * iter << " " ; 
    } 
    cout << endl ;
    
    cout << "first val is: " << my_array . front ( ) << endl ;  //front(): returns a direct reference to the first element in the container 
    cout << "last val is: " << my_array . back ( ) << endl ;    //back(): Returns the direct application of the last element in the container
    
    cout << "now filling the array with 0.01" << endl ; 
    my_array . fill ( 0.01 ) ; 
    for  ( int i =  0 ; i < my_array . size ( ) ; i ++ ) // call the size() member function to use for traverse 
    { 
        cout << my_array [ i ] << " " ; //array container can access elements randomly like normal array 
    } 
    cout << endl ;

    array < double , 10 > temp { } ; //Create a new Array container 
    my_array . swap ( temp ) ; //Swap two array containers

    for  ( int i =  0 ; i < my_array . size ( ) ; i + =  2 ) 
    { 
        my_array . at ( i )  = i * 2 ;  //at(): returns a reference to the element at position n in the container, n overflows An out_of_range exception will be thrown. 
    }

    array < double , 10 > :: reverse_iterator r_iter ; // define a reverse iterator 
    for  ( r_iter = my_array . rbegin ( ) ; r_iter != my_array . rend ( ) ; r_iter ++ ) 
    { //rbegin(): Returns a random access iterator pointing to the last element. 
     //rend(): Returns a random access iterator pointing to a position before the first element. 
        cout << * r_iter << " " ; 
    } 
    cout << endl ;

    getchar ( ) ; 
    return  0 ; 
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54

output:

array is not empty!
4 0.4 8.2 5.3 8.9 0.4 9.9 100.3 0 0
first val is: 4
last val is: 0
now filling the array with 0.01
0.01 0.01 0.01 0.01 0.01 0.01 0.01 0.01 0.01 0.01
0 16 0 12 0 8 0 4 0 0
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

array<T,N>The commonly used member functions and their roles have been commented in the above program.

begin()/end(), rbegin()/rend(), cbegin()/cend() and crbegin()/crend()

The C++11 standard library also adds two new functions, begin() and end(). The objects operated by these two functions can be not only containers, but also ordinary arrays. If the operation objects are ordinary arrays, begin() What is returned is a pointer to the first element of the array, and end() returns a pointer to the position after the last element (not the last).

# include <iostream>
 # include <array>
 using  namespace std ;

int  main ( ) 
{ 
    int arr [ 5 ]  =  { 1 , 2 , 3 , 4 , 5 } ; 
    int  * ptr ; 
    cout << "first: " << * begin ( arr ) << endl ; 
    ptr =  end ( arr ) ; 
    cout << "last : " << * ( -- ptr )<< endl ; //Pay attention to the first -- oh! 
    getchar ( ) ; 
    return  0 ; 
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

output:

first: 1
last : 5
  • 1
  • 2

Likewise, you can use the global begin() and end( ) functions to get iterators from the container.

auto first = std :: begin ( value ) ; 
auto last = std :: end ( value ) ;
  • 1
  • 2

The usage of rbegin()/rend(), cbegin()/cend(), crbegin()/crend() is similar to the usage of begin()/end(), except that rbegin()/rend() is used for iterator reverse order, The iterators returned by the cbegin()/cend(), crbegin()/crend() member functions can be used to traverse the elements in the container, and can also access the elements, but cannot modify the stored elements .

Notes :

  • When using reverse iterators rbegin()/rend() and crbegin()/crend() for ++ and – operations, ++ refers to moving the iterator one bit to the left, and – means moving the iterator one bit to the right bit.
access elements in an array container

Method 1: Like a normal array, usecontainer name[]way to directly access and use the elements in the container

array < int , 3 > val { 1 , 2 , 3 } ; 
val [ 2 ]  = val [ 1 ]  *  5  + val [ 0 ]  *  2 ;
  • 1
  • 2

Note: Using this method will not report an error if out of bounds

Method 2: Use the member function at()

array < int , 3 > val { 1 , 2 , 3 } ; 
val . at ( 2 )  =  val ( 1 ) * 5  +  val ( 0 ) * 2 ;
  • 1
  • 2

Note: this method will throw an error std::out_of_range if it is out of bounds

Method 3: Template functionget<n>

# include <iostream>
 # include <array>
 using  namespace std ; 
int  main ( ) 
{ 
    array < int , 5 > val { 1 , 2 , 4 , 5 , 3 } ; 
    cout << "last : " << get < 2 > ( val ) << endl ; // return element 4 
    for  ( int i = 0 ; i < val . size ( ) ; i ++ ) 
    { 
        cout << get < i > ( val ) << " " ; //Error! will report an error! 
    } 
    getchar ( ) ; 
    return  0 ; 
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

Note: This method will report an error if it is out of bounds, and the actual parameter of the parameter must be a constant expression that can be determined at compile time, not a loop variable!

Method 4: Member function data(), which returns a pointer to the first element of the container.

# include <iostream>
 # include <array>
 using  namespace std ; 
int  main ( ) 
{ 
    array < int , 5 > val { 1 , 2 , 4 , 5 , 3 } ; 
    for  ( int i =  0 ; i < val . size ( ) ; i ++ ) 
    { 
        cout <<* ( val . data ( ) + i ) << " " ; 
    } 
    getchar ( ) ; 
    return  0 ; 
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

vector<T> vector container

head File:#include<vector>

Features : It can dynamically adjust the occupied memory space, and is good at inserting/deleting elements at the end.

create a vector

std :: vector < int > int_vec ; //Create a vector container of type int 
std :: vector < double > double_vec { 0.2 , 4.2 , 3.99 } ; // Specify the initial value and the number of elements during initialization 
std :: vector < char >  char_vec ( 5 ) ; // create a vector container with 5 elements of type char, default value is 0 
std :: vector < int >  temp ( 10 , 2 ) ;//Create a vector container with 10 elements of type int and the default value is 2 
std :: vector < int >  temp2 ( temp ) ; //Create your own vector container from other containers
  • 1
  • 2
  • 3
  • 4
  • 5

Note: usingstd::vector<int> temp(10,2);When creating a vecotr container, the two parameters can be either constants or variables.

vector member functions

Let's briefly introduce the role of vector member functions through an example:

# include <iostream>
 # include <vector>
 using  namespace std ;

int  main ( ) 
{ 
    std :: vector < int > int_vec { 1 , 9 , 8 , 8 , 0 , 3 , 2 , 1 } ; 
    for  ( int i =  0 ; i < int_vec . size ( ) ; i ++ ) //Use the size() member function to traverse the vector container 
    { //size(): returns the number of container elements 
        cout <<int_vec [ i ] << " " ; // access the container elements like a normal array 
    } 
    cout << endl ;
    
    cout << "push a 25 at last!" << endl ; 
    int_vec . push_back ( 25 ) ; //push_back(): add an element at the end of the sequence 
    // you can also use the emplace_back() member function, which is the same as push_back , but the former is faster. 
    vector < int > :: iterator iter ; 
    for  ( auto iter = int_vec . begin ( ) ; iter != int_vec . end ( ) ; iter ++ ) // traverse the vector container through the begin() and end() member functions
    { //begin(): returns an iterator pointing to the first element in the container 
     //end(): returns an iterator pointing to the position after the last element of the container 
        cout << * iter << " " ; 
    } 
    cout << endl ; 
    cout << "pop 3 elem at last" << endl ; 
    for  ( int i =  0 ; i <  3 ; i ++ ) 
    { 
        cout << "the elem which is poped is :" << int_vec . back ( ) <<endl ;
        //back(): returns a reference to the last element 
        int_vec.pop_back ( ) ; //pop_back(): removes the element at the end of the sequence } cout << 
    " now the vector's size is : " << int_vec.size ( ) << endl ; 
    cout << "we change the size to nowsize * 2" << endl ; 
    int_vec . resize ( int_vec . size ( ) * 2 ) ; //resize(): Change the actual number of elements. int * ptr =
        
    
     int_vec.data ( ) ; // data () : Returns a pointer to the first element in the container. for ( int i = 0 ; i < int_vec . size ( ) ; i = i + 2 ) { 
        cout << * ( ptr + i ) << " " ; } 
    cout << endl ; 
    vector < int > temp { 1 , 1
      
    
    , 0 } ; 
    int_vec . swap ( temp ) ; //swap(): swap all elements of two containers 
    for  ( int i =  0 ; i < int_vec . size ( ) ; i ++ ) 
    { 
        cout << int_vec . at ( i ) << " " ; //at(): Access elements using bounds-checked indices. Out of bounds will throw an exception~ 
    } 
    cout << endl ; 
    getchar ( ) ;
    return  0 ;  
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50

output:

1 9 8 8 0 3 2 1
push a 25 at last!
1 9 8 8 0 3 2 1 25
pop 3 elem at last
the elem which is poped is :25
the elem which is poped is :1
the elem which is poped is :2
now the vector's size is : 6
we change the size to nowsize * 2
1 8 0 0 0 0
1 1 0
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

vector<T>The commonly used member functions and their roles have been commented in the above program. We can find that most of these includearray<T,N>The member function in , and the function is similar, such as begin() points to the first element, end() points to a position after the tail element.

Notes :

  • In addition to the member function swap(), the vector container also has a std::swap(x,y) non-member function, but note that the two must store elements of the same type.

  • The swap() member function of the vector container swaps the data in the two containers and also changes its size.

  • A vector container can be initialized as an empty container because its length is variable, but when initializing an empty vector container, iterators cannot be used, because for an empty vector container, both begin() and end() point to same location. If you want to initialize at this time, you can initialize by calling push_back() or resize() function.

    # include <iostream>
     # include <vector>
     using  namespace std ; 
    int  main ( ) { 
        vector < int > val ;
    
        for ( auto iter = val . begin ( ) ; iter != val . end ( ) ; iter ++ ) 
        { // no output 
            * iter =  1 ; 
            cout << * iter << " " ; 
        } 
        cout << "* *************" << endl ; 
        val . resize ( 10 ) ; //Resize the vector container 
        for (auto iter = val . begin ( ) ; iter != val . end ( ) ; iter ++ ) 
        { 
            * iter =  1 ; 
            cout << * iter << " " ; 
        } 
        getchar ( ) ; 
        return  0 ; 
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    output:

    ****************
    1 1 1 1 1 1 1 1 1 1
    
    • 1
    • 2
  • If you want to increase the capacity of the container, you can also use the member function reserve() to achieve the goal, but while applying for more memory, the storage address of the elements in the container will change (it can be said that a new memory storage area is found to storage)

    # include <iostream>
     # include <vector>
     using  namespace std ; 
    int  main ( ) { 
        vector < int > val { 1 , 2 , 4 , 5 } ; 
        cout << "old address : " << val . data ( ) < < endl ; 
        val . reserve ( 10 ) ; 
        cout <<"new address : " << val . data ( ) << endl ; 
        for  ( auto i = val . begin ( ) ; i != val . end ( ) ; i ++ ) 
        { 
            cout << * i << " " ; 
        } 
        cout << endl ; 
        cout << "the val's size is : " << val .size () << endl ;
    
        vector < int > temp { 1 , 2 , 3 , 4 } ; 
        temp . resize ( 10 ) ; 
        for  ( auto iter = temp . begin ( ) ; iter != temp . end ( ) ; iter ++ ) 
        { 
            cout << * iter << " " ; 
        } 
        cout<< endl ; 
        cout << "the temp's size is : " << temp . size ( ) << endl ; 
        getchar ( ) ; 
        return  0 ; 
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    output:

    old address : 0xef4320
    new address : 0xef4360
    1 2 4 5
    the val's size is : 4
    1 2 3 4 0 0 0 0 0 0
    the temp's size is : 10
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    It can be seen that the address is changed after calling reserve(), and only 4 elements are displayed after traversal. This is because the space opened up by reserve() does not mean all valid space, only the size of size() is valid space.

    Note: If you call reserve(n) where n is less than the original capacity, this function does nothing.

    The specific difference between reserve() and resize() can be found in these articleshttp://www.ifindbug.com/doc/id-44469/name-The difference between resize() and reserve in STL vector.html

    http://c.biancheng.net/view/6770.html

Detailed explanation of insert operation insert() and emplace()

The function of the insert() function is to insert one or more elements at the specified position of the vector container.

The specific usage (the insertion method in 4) is as follows:

# include <iostream>
 # include <vector>

using  namespace std ;

int  main ( ) 
{ 
    vector < int > vec { 1 , 2 , 3 , 4 , 5 , 6 } ; 
    vector < int > :: iterator iter ; 
    vec . insert ( vec . begin ( ) + 2 , 10 ) ; // Insert int element 10 before begin()+2 (3)th position 
    for  ( auto && val :vec ) 
    { 
        cout << val << " " ; 
    } 
    cout << endl ; 
    vec . insert ( vec . end ( ) - 1 , 3 , 9 ) ; // insert 3 int elements 9 before the last element 
    for  ( auto && val : vec ) 
    { 
        cout << val << " " ; 
    } 
    cout << endl ;
    vec . insert ( vec . begin ( ) + 3 , { 10 , 9 , 8 , 7 } ) ; // insert list {10,9,8,7} before the 4th element 
    for  ( auto && val : vec ) 
    { 
        cout << val << " " ; 
    } 
    cout << endl ;    
    vector < int > add { 9 , 9 ,6 } ; 
    vec . insert ( vec . end ( ) , add . begin ( ) , add . end ( ) ) ; // insert the entire vector container at the end add 
    for  ( auto && val : vec ) 
    { 
        cout << val << " " ; 
    } 
    cout << endl ; 
    getchar ( ) ; 
    return  0 ;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37

output:

1 2 10 3 4 5 6
1 2 10 3 4 5 9 9 9 6
1 2 10 10 9 8 7 3 4 5 9 9 9 6
1 2 10 10 9 8 7 3 4 5 9 9 9 6 9 9 6
  • 1
  • 2
  • 3
  • 4

The emplace() function also inserts elements before the specified position, but only one element can be inserted at a time, not multiple.

Of course, it is also more efficient than the insert() function.

# include <iostream>
 # include <vector>
 using  namespace std ; 
int  main ( ) 
{ 
    vector < int > v { 1 , 2 , 3 } ; 
    v . emplace ( v . begin ( ) , 0 ) ; 
    for ( auto  && val : v ) 
    { 
        cout << val <<" " ; 
    } 
    cout << endl ; 
    getchar ( ) ; 
    return  0 ; 
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

output:

0 1 2 3
  • 1
Detailed explanation of delete operations pop_back(), erase(), remove() and clear()

Let's take a look at the code first:

# include <iostream>
 # include <vector>
 # include <algorithm>
 using  namespace std ;

int  main ( ) 
{ 
    vector < int > v { 1 , 9 , 9 , 9 , 0 , 6 , 0 , 2 } ; 
    cout << "test pop_back()" << endl ; 
    cout << "size is : " < < v . size ( ) << endl ; 
    cout << "capacity is : " << v .capacity( ) << endl ; 
    cout << "pop last one : " << v . back ( ) << endl ; 
    v . pop_back ( ) ; 
    cout << "size is : " << v . size ( ) << endl ; 
    cout << "capacity is : " << v . capacity ( ) << endl << endl ; 
    // this time v{1,9,9,9,0,6,0} 
    cout<< "test erase()" << endl ; 
    auto iter = v . erase ( v . begin ( ) + 2 ) ; // delete the element at the specified position and return an iterator pointing to the position next to the deleted element. 
    for ( auto i = iter ; i != v . end ( ) ; i ++  ) //Start traversing after the iterator 
    { 
        cout << * i << " " ; 
    } 
    cout <<endl ; 
    cout << "size is : " << v . size ( ) << endl ; 
    cout << "capacity is : " << v . capacity ( ) << endl << endl ; 
    // this time v{1 ,9,9,0,6,0}   
    cout << "test another erase()" << endl ; 
    iter = v . erase ( v . begin ( ) , v .begin () + 3 ) ; //remove the element in the [first, last) region and return an iterator pointing to a position after this region 
    for ( auto i = iter ; i != v . end ( ) ; i ++  ) 
    { 
        cout << * i << " " ; 
    } 
    cout << endl ; 
    cout << "size is : " << v . size ( ) << endl ; 
    cout <<"capacity is : " << v . capacity ( ) << endl << endl ; 
    // at this point v{0,6,0}     
    cout << "test remove()" << endl ; 
    iter =  remove ( v . begin ( ) , v . end ( ) , 0 ) ; // delete all elements with element 0 in the specified area 
    for ( auto i = v . begin ( ) ; i !=iter ; i ++ ) 
    { 
        cout << * i << " " ; 
    } 
    cout << endl ; 
    for ( auto i = v . begin ( ) ; i != v . end ( )  ; i ++ ) 
    { 
        cout < < * i << " " ; 
    } 
    cout << endl ; 
    cout <<"size is : " << v . size ( ) << endl ; 
    cout << "capacity is : " << v . capacity ( ) << endl << endl ; 
    // this time v{6,6,0} 
    cout << "test clear()" << endl ; 
    v . clear ( ) ; // delete all elements in the container 
    cout << endl ; 
    cout << "size is : " <<v . size () << endl ; 
    cout << "capacity is : " << v . capacity ( ) << endl << endl ;

    getchar ( ) ; 
    return  0 ; 
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60

output:

test pop_back()
size is : 8
capacity is : 8
pop last one : 2
size is : 7
capacity is : 8

test erase()
9 0 6 0
size is : 6
capacity is : 8

test another erase()
0 6 0
size is : 3
capacity is : 8

test remove()
6
6 6 0
size is : 3
capacity is : 8

test clear()

size is : 0
capacity is : 8
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

pop_back() , the function usage is very simple, that is, delete the last element in the vector container, the size of the container will be reduced by 1, but the capacity will not change.

erase(pos) , deletes the element in the vector container at the position specified by the pos iterator, and returns an iterator pointing to the element at the next position of the deleted element. The size of the container (size) will be reduced by 1, but the capacity (capacity) will not change.

erase(pos1,pos2) , deletes the element at [pos1,pos2) in the vector container and returns an iterator pointing to the element at the next position in the deleted region. The size of the container (size) will be reduced by pos2-pos1, but the capacity (capacity) will not change.

remove() , removes all elements in the container whose value is equal to the specified element, and returns an iterator pointing to the next position of the last element. It is worth mentioning that calling this function does not change the size and capacity of the container.

  • Note : Looking at the output, we can see that after removing the element through remove(), the size has not changed, and the output after traversing the container is6 6 0,Why is this? This is because the implementation principle of remove() is that when traversing the elements in the container, once the target element is encountered, mark it, and then continue to traverse until a non-target element is found, that is, this element will be used to mark the first element (that is, the original 0 is covered with the second 6, but the original 6 is not covered, and the last 0 will not be covered because there is no element behind it), and the position of the non-target element is also covered. Make a mark and wait for a new non-target element to be found to overwrite it.

clear() , removes all elements in the vector container, making it an empty vector container. This function changes the size of the vector (to 0), but not its capacity.

deque <T> deque container

head File:#include<deque>

Features : It can dynamically adjust the occupied memory space, and is good at inserting/deleting elements at the head/tail.

create a deque

std :: deque < int > int_deque ; //Create a deque container of type int 
std :: deque < double > double_deque { 0.2 , 4.2 , 3.99 } ; // Specify the initial value and the number of elements during initialization 
std :: deque < char >  char_deque ( 5 ) ; // create a deque container with 5 elements of type char, default value is 0 
std :: deque < int >  temp ( 10 , 2 ) ;//Create a deque container with 10 elements of type int and the default value is 2 
std :: deque < int >  temp2 ( temp ) ; // create your own deque container through other containers
  • 1
  • 2
  • 3
  • 4
  • 5

deque member function

The deque<T> member functions are mostly the same and act similarly to the array<T,N> and vector<T> member functions. But deque supports adding and removing elements from the container header, and it removes the capacity(), reserve() and data() member functions.

# include <iostream>
 # include <deque>
 using  namespace std ;

int  main ( ) 
{ 
    std :: deque < int > int_deque ; 
    for  ( int i =  0 ; i <  3 ; i ++ ) 
    { 
        int_deque . push_front ( i ) ; 
    } 
    for  ( int i =  0 ; i <  3 ; i ++ ) 
    { 
        int_deque . push_back( i ) ; 
    }    
    auto iter = int_deque . begin ( ) ; 
    for  ( auto i = iter ; i != int_deque . end ( ) ; i ++ ) 
    { 
        cout << * i << " " ; 
    } 
    cout << endl ; 
    for  ( int i =  0 ; i <  4; i ++ ) 
    { 
        int_deque . pop_front ( ) ; 
    } 
    for  ( auto i = int_deque . begin ( ) ; i != int_deque . end ( ) ; i ++ ) 
    { 
        cout << * i << " " ; 
    } 
    cout << endl ; 
    getchar ( ) ; 
    return  0 ; 
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33

output:

2 1 0 0 1 2
1 2
  • 1
  • 2

Compared with vector, deque has two unique member functions push_front() and pop_front().

push_front() : Adds an element to the head of the container's existing elements. emplace_front() is similar but more efficient.

pop_front() : Remove an element at the end of the container.

The rest of the member functions are similar to the previous ones, so I won't go into details~, you can see the table below.

member functionFeatures
push_back()Adds an element to the end of the container's existing elements. Unlike emplace_back(), this function adds a new element by constructing the element and then moving or copying the element to the end of the container.
pop_back()Removes an element from the end of the container.
emplace_back()Generates an element at the end of the container. Unlike push_back(), this function constructs the element directly in the container header, eliminating the need to copy or move the element.
emplace_front()Generates an element at the head of the container. Unlike push_front(), this function constructs the element directly at the head of the container, eliminating the need to copy or move the element.
insert()Generates an element directly at the specified position. Unlike emplace(), this function adds a new element by constructing the element and then moving or copying the element to the specified location of the container. Note: The insertion method is similar to vector, there are 4 kinds
emplace()Generates an element directly at the specified position. Unlike insert(), emplace() constructs the element directly at the specified position in the container, eliminating the need to copy or move the element.
erase()Removes an element or multiple elements within a range.

list<T> Doubly linked list container

head File:#include<list>

Features : The elements in the list container can be scattered and stored in the memory space, and the occupied memory space can be dynamically adjusted to quickly insert or delete elements at any position known in the sequence.

create a list

A brief introduction to the five methods of list creation:

The first is several creation methods that are very similar to vector:

std :: list < int > int_list ; //Create a list container of type int 
std :: list < double > double_list { 0.2 , 4.2 , 3.99 } ; // Specify the initial value and the number of elements during initialization 
std :: list < char >  char_liste ( 5 ) ; // create a list container with 5 elements of type char, default value is 0 
std :: list < int >  temp ( 10 , 2 ) ;//Create a list container with 10 elements of type int and the default value is 2 
std :: list < int >  temp2 ( temp ) ; //Create your own list container from other containers
  • 1
  • 2
  • 3
  • 4
  • 5

It can also be created in the following two ways:

# include <iostream>
 # include <list>
 # include <array>
 using  namespace std ;

int  main ( ) 
{ 
    //Copy other types of containers to create a list container 
    array < int , 5 > a { 1 , 2 , 3 , 4 , 5 } ; 
    list < int >  ls1 ( a . begin ( ) + 1 , a .end ( ) ) ; for ( auto && val : ls1 ) { _
      
    
        cout << val << " " ; 
    } 
    cout << endl ; 
    //Copy the normal array and create a list container 
    int arr [ ]  =  { 9 , 8 , 7 , 6 , 5 } ; 
    list < int >  ls2 ( arr , arr + 4 ) ; 
    for  ( auto  && val : ls2 ) 
    { 
        cout << val<< " " ; 
    } 
    cout << endl ; 
    getchar ( ) ; 
    return  0 ; 
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

output:

2 3 4 5
9 8 7 6
  • 1
  • 2

list member function

First of all, the begin()/end(), rbegin()/rend(), cbegin()/cend(), crbegin()/crend() member functions of list are the same usage as array, vector, and deque.

Note: The biggest difference between the list container iterator and vector, array, and deque is that the iterator type it is equipped with is a bidirectional iterator instead of a random access iterator.

Therefore, assuming that p1 and p2 are bidirectional iterators, they support the use of the ++p1, p1++, p1–, p1++, *p1, p1==p2, and p1!=p2 operators, but not the following (where i is an integer):

  • p1[i]: The element at the specified position in the list container cannot be accessed by subscripting.
  • p1-=i, p1+=i, p1+i , p1-i: bidirectional iterator p1 does not support the use of -=, +=, +, - operators.
  • p1<p2, p1>p2, p1<=p2, p1>=p2: Bidirectional iterators p1, p2 do not support the use of the <, >, <=, >= comparison operators.
Insert operations emplace(), emplace_front(), emplace_back(), insert() and splice()
# include <iostream>
 # include <list>
 # include <array>
 using  namespace std ;

int  main ( ) 
{ 
    list < int > ls { 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 } ; 
    cout << "first is : " << ls .front ( ) << endl ; 
    cout << "last is : " << ls . back ( ) << endl; 
    cout << "add in last :" << 6 << endl ; 
    ls . emplace ( ls . end ( ) , 6 ) ; 
    cout << "add in front :" << 100 << endl ; 
    ls . emplace ( ls . begin ( ) , 100 ) ; 
    for  ( auto  && val : ls ) 
    { 
        cout<< val << " " ; 
    } 
    cout << endl ;     
    list < int > temp { 1 , 11 , 111 , 1111 } ; 
    auto start = temp . begin ( ) ; 
    auto end = temp . end ( ) ; 
    ls . splice ( ++ ls.begin ( ) , _ _temp ) ; 
    for  ( auto  && val : ls ) 
    { 
        cout << val << " " ; 
    } 
    cout << endl ; 
    cout << "temp size is: " << temp . size ( ) << endl ; 
    cout << "*********" << endl ; 
    list < int > ano { 9 , 99 ,999} ; 
    ls . splice ( ls . begin ( ) , ano , ano . begin ( ) , ano . end ( ) ) ; 
    for  ( auto i = ls . begin ( ) ; i != ls . end ( ) ; i ++ ) 
    { 
        cout << * i << " "; 
    } 
    cout << endl ; 
    getchar ( ) ; 
    return  0 ; 
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40

output:

first is : 1
last is : 10
add in last :6
add in front :100
100 1 2 3 4 5 6 7 8 9 10 6
100 1 11 111 1111 1 2 3 4 5 6 7 8 9 10 6
temp size is: 0
*********
9 99 999 100 1 11 111 1111 1 2 3 4 5 6 7 8 9 10 6
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

Note: Once the member function splice() is called to move elements from list1 to list2, those elements no longer exist in list1.

Remove operations pop_front(), pop_back(), erase(), remove(), unique() and remove_if()

pop_front(), pop_back() operations:

# include <iostream>
 # include <list>
 using  namespace std ; 
int  main ( ) 
{ 
    list < int > ls { 1 , 9 , 9 , 9 , 0 , 1 , 0 , 1 } ; 
    for  ( auto i = ls . begin ( ) ; i != ls . end () ; i ++ ) 
    { 
        cout << * i << " " ; 
    } 
    cout << endl ; 
    cout << "size is : " << ls . size ( ) << endl ; 
    cout << "pop one from front .\n" ; 
    ls . pop_front ( ) ; 
    ls . pop_back ( ) ; 
    cout << "pop one from last.\n";
    for  ( auto i = ls . begin ( ) ; i != ls . end ( ) ; i ++ ) 
    { 
        cout << * i << " " ; 
    } 
    cout << endl ; 
    cout << "now size is : " << ls . size ( ) << endl ; 
    getchar ( ) ; 
    return  0 ;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

output:

1 9 9 9 0 1 0 1
size is : 8
pop one from front.
pop one from last.
9 9 9 0 1 0
now size is : 6
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

It can be seen that pop_front() deletes an element at the head of the list container. pop_back() removes an element at the end of the list container. Both will reduce the container size (size) by one.

erase() operation:

# include <iostream>
 # include <list>

using  namespace std ;

int  main ( ) 
{ 
    list < int > ls { 1 , 9 , 9 , 9 , 0 , 1 , 0 , 1 } ; 
    for  ( auto i = ls . begin ( ) ; i != ls . end ( ) ; i + + ) 
    { 
        cout << * i << " "; 
    } 
    cout << endl ; 
    cout << "size is : " << ls . size ( ) << endl ; 
    cout << "erase one from pos 5.\n" ; 
    auto iter = ls . begin ( ) ; 
    for  ( int i =  0 ; i <  4 ; i ++ ) 
    { 
        iter ++ ; 
    } 
    ls .erase ( iter ) ; 
    for  ( auto i = ls . begin ( ) ; i != ls . end ( ) ; i ++ ) 
    { 
        cout << * i << " " ; 
    } 
    cout << endl ; 
    cout << " now size is : " << ls . size ( ) << endl ;

    cout << "erase datas from pos 1 to pos 3.\n" ; 
    auto begin = ls . begin ( ) ; 
    auto end = begin ; 
    for  ( int i =  0 ; i <  3 ; i ++ ) 
    { 
        end ++ ; 
    } 
    ls . erase ( begin , end ) ; 
    for  ( auto i = ls .begin ( ) ; i != ls . end ( ) ; i ++ ) 
    { 
        cout << * i << " " ; 
    } 
    cout << endl ; 
    cout << "now size is : " << ls . size ( ) << endl ;     
    getchar ( ) ; 
    return  0 ; 
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45

output:

1 9 9 9 0 1 0 1
size is : 8
erase one from pos 5.
1 9 9 9 1 0 1
now size is : 7
erase datas from pos 1 to pos 3.
9 1 0 1
now size is : 4
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

As can be seen from the above, the erase() member function has two usage syntaxes. They are:

function prototypeFeatures
iterator erase (iterator position);removes the element at the position pointed to by the position iterator in the list container
iterator erase (iterator first, iterator last);Deletes all elements in the range bounded by the first iterator and the last iterator in the list container (including the element pointed to by first, but not the element pointed to by last)

remove() operation:

# include <iostream>
 # include <list>
 using  namespace std ; 
int  main ( ) 
{ 
    list < int > ls { 1 , 9 , 9 , 9 , 0 , 1 , 0 , 1 } ; 
    for  ( auto i = ls . begin ( ) ; i != ls . end () ; i ++ ) 
    { 
        cout << * i << " " ; 
    } 
    cout << endl ; 
    cout << "size is : " << ls . size ( ) << endl ; 
    cout << "remove num 1\ n" ; 
    ls . remove ( 1 ) ; 
    for  ( auto i = ls . begin ( ) ; i!= ls . end ( ) ; i ++ ) 
    { 
        cout << * i << " " ; 
    } 
    cout << endl ; 
    cout << "now size is : " << ls . size ( ) << endl ;     
    getchar ( ) ; 
    return  0 ; 
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

output:

9 9 9 0 1 0 1
size is : 8
remove num 1
9 9 9 0 0
now size is : 5
  • 1
  • 2
  • 3
  • 4
  • 5

So if you want to perform a delete operation based on the value of an element, you can use the remove() member function.

unique() operation:

# include <iostream>
 # include <list>
 using  namespace std ; 
bool  unique_demo ( int a , int b ) 
{ 
    return  ( a + b )  %  2  ==  0 ; 
} 
int  main ( ) 
{ 
    list < int > ls { 1 , 9 , 9 , 9 , 0 , 1 ,0 , 1 } ; 
    for  ( auto i = ls . begin ( ) ; i != ls . end ( ) ; i ++ ) 
    { 
        cout << * i << " " ; 
    } 
    cout << endl ; 
    cout << " size is : " << ls . size ( ) << endl ; 
    cout <<"after unique()\n" ; 
    ls . unique ( ) ; 
    for  ( auto i = ls . begin ( ) ; i != ls . end ( ) ; i ++ ) 
    { 
        cout << * i << " " ; 
    } 
    cout << endl ; 
    cout << "now size is : " << ls . size ( ) <<endl ;    

    ls . unique ( unique_demo ) ; 
    for  ( auto i = ls . begin ( ) ; i != ls . end ( ) ; i ++ ) 
    { 
        cout << * i << " " ; 
    } 
    cout << endl ; 
    cout < < "now size is : " << ls . size ( ) << endl ;      
    getchar ( ) ; 
    return  0 ; 
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35

output:

1 9 9 9 0 1 0 1
size is : 8
after unique()
1 9 0 1 0 1
now size is : 6
1 0 1 0 1
now size is : 5
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

The unique() function also has the following 2 syntax formats:

function prototypeFeatures
void unique()Remove adjacent duplicate elements from the list container
void unique(BinaryPredicate)//Pass in a binary predicate functionRemove elements that meet the requirements according to the rules of the binary predicate function

You can see that we have defined a binary predicate function bool unique_demo(int a,int b) above. By passing the custom predicate function to the unique() member function, the elements in the list container that enable the predicate function to be established will be Delete (that is, if the addition of the two elements a, b before and after is an even number, remove the second element b).

remove_if() operation:

# include <iostream>
 # include <list>
 using  namespace std ; 
int  main ( ) 
{ 
    list < int > ls { 2 , 4 , 6 , 8 , 72 , 12 , 4 , 65 } ; 
    ls . remove_if ( [ ] ( int value ) { return value > 50 ;} ) ; 
    for  ( auto i = ls . begin ( ) ; i != ls . end ( ) ; i ++ ) 
    { 
        cout << * i << " " ; 
    } 
    cout << endl ; 
    cout << "now size is : " << ls . size ( ) << endl ;   
    getchar ( ) ;
    return  0 ; 
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

output:

2 4 6 8 12 4
now size is : 6
  • 1
  • 2

By passing a custom predicate function (unlimited number of parameters) to the remove_if() member function, the elements in the list container that make the predicate function valid will be removed.

forward_list<T> singly linked list container

head File:#include<forward_list>

Features : The elements in the forward_list container can be scattered and stored in the memory space, the memory space occupied can be dynamically adjusted, and the memory space consumed is less than that of the list, and the space utilization rate is higher, so that it can be quickly used in any position where the sequence is known. Insert or delete elements. The forward_list container only provides forward iterators, not bidirectional iterators.

Note: High efficiency is the main reason for choosing forward_list and discarding the list container. In other words, as long as the operation can be achieved by both the list container and the forward_list container, the forward_list container should be preferred.

Create a forward_list

std :: forward_list < int > int_forward_list ; //Create a forward_list container of type int 
std :: forward_list < double > double_forward_list { 0.2 , 4.2 , 3.99 } ; // Specify the initial value and the number of elements during initialization 
std :: lisforward_listt < char >  char_forward_list ( 5 ) ; // create a forward_list container with 5 elements of type char, default value is 0 
std :: forward_list < int >  temp ( 10, 2 ) ; //Create a forward_list container with 10 elements of type int and a default value of 2 
std :: forward_list < int >  temp2 ( temp ) ; //Create your own forward_list container through other containers
  • 1
  • 2
  • 3
  • 4
  • 5

forward_list member function

# include <iostream>
 # include <forward_list>
 using  namespace std ;

int  main ( ) 
{ 
    forward_list < int > fls { 1 , 2 , 4 , 5 , 7 , 9 , 3 , 0 , 15 } ; 
    cout << "the forward_list length is : " << distance ( fls . begin ( ) , fls . end ( ) ) << endl ; 
    int len = distance ( fls . begin ( ) , fls . end ( ) ) ; 
    for  ( auto i = fls . begin ( ) ; i != fls . end ( )  ; i ++ ) 
    { 
        cout << * i << " " ; 
    } 
    cout << endl ; 
    fls . sort ( ); 
    for  ( auto i = fls . begin ( ) ; i != fls . end ( )  ; i ++ ) 
    { 
        cout << * i << " " ; 
    } 
    cout << endl ; 
    fls . reverse ( ) ; 
    for  ( auto i = fls . begin ( ) ; i !=fls . end ( )  ; i ++ ) 
    { 
        cout << * i << " " ; 
    } 
    cout << endl ; 
    getchar ( ) ; 
    return  0 ; 
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29

output:

the forward_list length is : 9
1 2 4 5 7 9 3 0 15
0 1 2 3 4 5 7 9 15
15 9 7 5 4 3 2 1 0
  • 1
  • 2
  • 3
  • 4

The above is just a few examples of the use of member functions. The usage of other idiom functions is similar to the usage of member functions of the previous container.

Notice! The size() function is not provided in the forward_list container, but if you want to get the number of elements stored in the forward_list container, you can use the header file<iterator>distance() function in .

member functionFeatures
before_begin()Returns a forward iterator pointing to the position before the first element in the container.
begin()Returns a forward iterator pointing to the position of the first element in the container.
end()Returns a forward iterator pointing to the position after the last element in the container.
cbefore_begin()It has the same function as before_begin(), except that on its basis, the const attribute is added, which cannot be used to modify the element.
cbegin()It has the same function as begin(), except that on its basis, the const attribute is added, which cannot be used to modify the element.
cend()It has the same function as end(), except that on its basis, the const attribute is added, which cannot be used to modify the element.
empty()Determine whether there is an element in the container, if there is no element, return true; otherwise, return false.
max_size()Returns the maximum number of elements the container can contain. This is usually a large value, typically 232-1, so we rarely use this function.
front()Returns a reference to the first element.
assign()Replace the original contents of the container with the new element.
push_front()Inserts an element at the head of the container.
emplace_front()Generates an element at the head of the container. This function is the same as push_front(), but more efficient.
pop_front()Removes an element from the head of the container.
emplace_after()Inserts a new element after the specified position and returns an iterator pointing to the new element. Same function as insert_after(), but more efficient.
insert_after()Inserts a new element after the specified position and returns an iterator pointing to the new element.
erase_after()Removes all elements within a specified location or area of ​​the container.
swap()To exchange elements in two containers, it must be ensured that the types of elements stored in the two containers are the same.
resize()Resize the container.
clear()Removes all elements stored by the container.
splice_after()Inserts an element in a forward_list container at the specified position or range after the specified position in another container.
remove(val)Removes all elements equal to val from the container.
remove_if()Removes elements from the container that satisfy the condition.
unique()Remove adjacent duplicate elements in the container, leaving only one.
merge()Merge two pre-ordered forward_list containers, and the merged forward_list container is still ordered.
sort()Sorts elements by changing their position in the container.
reverse()Reverse the order of elements in the container.

Related: STL sequential container (array, vector, deque, list) learning summary