This is the 16th day of my participation in the August More Text Challenge. For details, see:August is more challenging

c++ vector

Introduction to the

  • A vector is a type of sequential container. A vector is a variable length dynamic array (which can hold any type) that supports random access iterators. All STL algorithms can operate on a vector. To use a vector, we need to include the header vector
  • advantages
    • Because it has a contiguous memory space, it can very well support random access, namely the [] operator.
    • The time it takes to randomly access an element based on the subscript is constant, and the time it takes to add an element to the tail is also constant most of the time, which is generally very fast
  • disadvantages
    • To represent a long vector (which requires a large number of vectors to be stored internally) can easily cause memory leaks and be very inefficient
    • Inserting or deleting elements in the middle is slow because you have to move multiple elements, and the average time taken is proportional to the number of elements in the container

Function list

  • Constructors: Constructors
  • Operators assign or compare elements in a vector
  • Assign () // Assign to the elements in the vector
  • At () // Returns the position of the specified element
  • Back () // Returns the last element
  • Begin () // Returns an iterator for the first element
  • Capacity () // returns the number of elements that the vector can hold (without reallocating memory)
  • Clear () // Clear all elements
  • Empty () // Determines whether the vector is empty(if empty returns true)
  • End () // Returns an iterator for the last element (actually next to the last element)
  • Erase () // Delete the specified element
  • Front () // Returns the first element
  • Get_allocator () // Returns the memory allocator of the vector
  • Insert () // Insert elements into the vector
  • Max_size () // returns the maximum number of elements that a vector can hold (upper limit)
  • Pop_back () // removes the last element
  • Push_back () // Adds an element to the end of the vector
  • Rbegin () // Returns the inverse iterator to the end of the vector
  • Rend () // Returns an inverse iterator starting with vector
  • Reserve () // sets the minimum number of elements that the vector can hold
  • Resize () // Resizes the number of elements in the vector
  • Size () // Returns the size of the number of elements in the vector
  • Seap () // Swap two vectors

The function,

  • The constructor

    • Grammar:
      • Vector () // takes no constructor to initialize the container to empty
      • Vector (int n) // Initialize the vector to have n elements
      • Vector (int n, const T & val) // Assuming that the element type is T, this constructor initializes the container to have n elements, each of which has the value val
    • case
    vector<int> v1(5.6);  // Construct a vector of five elements with value 6
    Copy the code
  • The assign function

    • Grammar:
      • void assign(input_iterator first, input_iterator last); // Assign the elements of the interval [first, last] to the current vector
      • void assign(size_type num, const TYPE & val); // Assign num elements with the value val to the vector
      • The assign function clears the vector before the assignment
    • case
    #include <iostream>
    #include <vector> 
    using namespace std;
    
    int main(a) {
        int a[5] = {1.2.3.4.5};
        int b[2] = {1.2};
        vector<int> v1(a, a + 5).v2(b, b + 2), v3;
        vector<int>::iterator iter;
        
        cout<<"v1 = ";
        for(iter = v1.begin(); iter ! = v1.end(); iter ++)cout<<*iter<<"";
            cout<<endl;
            
        cout<<"v2 = ";
        for(iter = v2.begin(); iter ! = v2.end(); iter ++)cout<<*iter<<"";
            cout<<endl;    
            
        v2 = v1;
        cout<<"v2 = ";
        for(iter = v2.begin(); iter ! = v2.end(); iter ++)cout<<*iter<<"";
            cout<<endl; 
            
        v2.assign(v1.begin(), v1.end());
        cout<<"v2 = ";
        for(iter = v2.begin(); iter ! = v2.end(); iter ++)cout<<*iter<<"";
            cout<<endl; 
            
        v3.assign(7.3);
        cout<<"v3 = ";
        for(iter = v3.begin(); iter ! = v3.end(); iter ++)cout<<*iter<<"";
            cout<<endl; 
            
        return 0;
    }
    Copy the code
      	v1 = 1 2 3 4 5 
      	v2 = 1 2 
      	v2 = 1 2 3 4 5 
      	v2 = 1 2 3 4 5 
      	v3 = 3 3 3 3 3 3 3 
    Copy the code
  • The ats function

    • Grammar:
      • TYPE at(size_type loc); // Return a reference to the elements at the position loc specified in the current vector
      • The at() function is safer than the [] operator. At () does not allow you to access elements that are out of bounds in the vector
    • Case 1
    // This code is accessed out of bounds and may lead to dangerous results
    #include <iostream>
    #include <vector> 
    using namespace std;
    
    int main(a) {
        vector<int> v;
        v.assign(6.6);
        for(int i = 0; i < 10; i ++)
            cout<<v[i]<<"";
        cout<<endl;
        return 0;
    }
    Copy the code
      	6 6 6 6 6 6 135137 0 0 0 
    Copy the code
    • Case 2
    // The modified code uses at() to throw an out_of_range exception when the boundary is crossed
    #include <iostream>
    #include <vector> 
    using namespace std;
    
    int main(a) {
        vector<int> v;
        v.assign(6.6);
        for(int i = 0; i < 10; i ++)
            cout<<v.at(i)<<"";
        cout<<endl;
        return 0;
    }
    Copy the code
      	6 6 6 6 6 6 
      	
      	terminate called after throwing an instance of 'std::out_of_range'
      	  what():  vector::_M_range_check
      	/usercode/script.sh: line 62:    13 Aborted                 $output - < "/usercode/inputFile"
    Copy the code
  • Erase function

    • Grammar:
      • iterator erase(iterator loc); // Delete the element at the specified location loc
      • iterator erase(iterator first, iterator last); // Delete all elements in the range [first, last]
      • Erase returns an iterator next to the last element to be removed
    • case
    // Create a veC and place the first ten characters of the alphabet
    #include <iostream>
    #include <vector> 
    using namespace std;
    
    int main(a) {
        vector<char> v;
        for(int i = 0; i < 10; ++ i)
            v.push_back(i + 65);
        int size = v.size();
        
        vector<char>::iterator startIterator;
        vector<char>::iterator tempIterator;
        
        for(int i = 0; i < size; i ++)
        {
            startIterator = v.begin();
            v.erase(startIterator);
            
            for(tempIterator = v.begin(); tempIterator ! = v.end(); tempIterator ++)cout<<*tempIterator;
            cout<<endl;
        }
        return 0;
    }
    Copy the code
      	BCDEFGHIJ
      	CDEFGHIJ
      	DEFGHIJ
      	EFGHIJ
      	FGHIJ
      	GHIJ
      	HIJ
      	IJ
      	J
    Copy the code
  • Get_allocator function

    • Grammar:
      • allocator_type get_allocator();
      • The get_allocator() function returns the memory allocator for the current vector. STL memory is not allocated by new or alloc, but by an allocator object
    • case
    vector3(3.1, v2.get_allocator());  // Take v2's memory allocator as a parameter to construct v3. Thus, both of them use one memory allocator.
    Copy the code

    The allocator class in c++

    An overview of the

    • It is used to separate memory allocation from object construction. The memory it allocates is raw, unconstructed.
    allocator<string> alloc;  // Defines an Allocator object that can allocate strings
    auto const p = alloc.allocate(n);  // Allocate n uninitialized string memory, that is, allocate n empty string memory, the allocated memory is raw, unconstructed
    Copy the code

    Allocator usage

    • Allocator a // Defines an Allocator object named a that allocates memory for objects of type T
    • A.allocate (n) // Allocate memory that can hold n objects of type T
    • Allocate (p, n) = allocate(p, n) = allocate(p, n) = allocate(p, n) = allocate(p, n) = allocate(p, n) = allocate(p, n) = allocate(p, n) This is because we allocate the most original memory during the creation process, so we can only strictly release the most original memory when freeing memory
    • C struct(p, args) // p must be a pointer of type T* to a piece of raw memory. Arg will be passed to a constructor of type T to build an object on the raw memory pointed to by p
    • A. destory(p) // p is a pointer of type T*, used to execute the destructor on the object to which p points

    Break down

    • Allocate is used to allocate raw memory

      • As mentioned earlier, allocate is the original, unconstructed memory. Its Construct member function takes a pointer and zero or more extra arguments to construct the object at the given location. The extra arguments are used to initialize the constructed object
      auto q = p;  // q refers to the position after the last constructed element
      alloc.construct(q++);  // *q is an empty string
      alloc.construct(q++, 10.'c');  / / * q for CCCCCCCCCC
      alloc.construct(q++, "hi");  / / * q for hi
      Copy the code
      • When the object is used up, you must call deStory destruction on the constructed object, which takes a pointer and executes the destructor on the object to which it points
      while(q ! = p) alloc.destory(--q);Copy the code

      At the beginning of the loop, q refers to a position after the last constructed element. We decrement q before calling deStory, so the first deStory call destroys the last element, and we continue until q and p are equal. Once the element is destroyed, we can reuse the memory to store other strings or return it to the system. Deallocate frees the memory by calling deallocate

      alloc.deallocate(p, n)
      Copy the code

      Where p cannot be empty and must point to the allocate allocated memory, and the size parameter n must also be equal to the size parameter provided when allocate memory is called

  • The insert function

    • Grammar:
    • iterator insert(iterator loc, const TYPE & val); // Insert an element with the value val before loc, and return an iterator to that element
    • void insert(iterator loc, size_type num, const TYPE & val); // Insert num (val) before loc
    • void insert(iterator loc, input_iterator first, input_iterator last); // Insert all elements of the interval [first, last] before the specified position loc
    • case
    // Create a veC and place the first ten characters of the alphabet
    #include <iostream>
    #include <vector> 
    using namespace std;
    
    int main(a) {
        vector<char> v;
        for(int i = 0; i < 10; ++ i)
            v.push_back(i + 65);
            
        // Insert four C's into the vector
        vector<char>::iterator theIterator = v.begin();
        v.insert(theIterator, 4.'C');
        
        // Display the contents of the vector
        for(theIterator = v.begin(); theIterator ! = v.end(); theIterator ++)cout<<*theIterator;
        cout<<endl;
        return 0;
    }
    Copy the code
      	CCCCABCDEFGHIJ
    Copy the code
  • Max_size function

    • Grammar:
      • size_type max_size();
      • The max_size() function returns the maximum number of elements that the current vector can hold (note: including realizable memory).
  • Pop_back () function

    • Grammar:
      • void pop_back(); // Delete the last element of the current vector
    • case
    #include <iostream>
    #include <vector> 
    using namespace std;
    
    int main(a) {
        vector<char> v;
        for(int i = 0; i < 10; ++ i)
            v.push_back(i + 65);
            
       int size = v.size();
       vector<char>::iterator theIterator;
       for(int i = 0; i < size; i ++){
           v.pop_back();
        for(theIterator = v.begin(); theIterator ! = v.end(); theIterator ++)cout<<*theIterator;
        cout<<endl;
       }
        return 0;
    }
    Copy the code
      	ABCDEFGHI
      	ABCDEFGH
      	ABCDEFG
      	ABCDEF
      	ABCDE
      	ABCD
      	ABC
      	AB
      	A
    Copy the code
  • Rbegin function

    • Grammar:
      • reverse_iterator rbegin(); // Return an inverse iterator to the end of the current vector (actually next to the end, but actually containing the value of the element at the end)
      • case
      #include <iostream>
      #include <vector> 
      using namespace std;
      
      int main(a) {
          vector<int> v;
          for(int i = 0; i <= 5; i ++)
              v.push_back(i);
          vector<int>::reverse_iterator pos;
          pos = v.rbegin();
          for(int i = 0; i <= 5; i ++)
          {
              cout<<*pos<<"";
              pos++;
          }
          return 0;
      }
      Copy the code
      5, 4, 3, 2, 1, 0Copy the code
  • Rend function

    • Grammar:
      • reverse_iterator rend(); // Return an inverse iterator to the start of the current vector
      • case
      #include <iostream>
      #include <vector> 
      using namespace std;
      
      int main(a) {
          vector<int> v;
          for(int i = 0; i <= 5; i ++)
              v.push_back(i);
          vector<int>::reverse_iterator pos;
          pos = v.rend();
          for(int i = 0; i <= 5; i ++)
          {
              pos--;
              cout<<*pos<<"";
          }
          return 0;
      }
      Copy the code
      0, 1, 2, 3, 4, 5Copy the code
  • Reserve function

    • Grammar:
      • void reserve(size_type size); // Set the current vector to hold at least size of elements (note: actual space may be larger than size)
  • The resize function

    • Grammar:
      • void resize(size_type size, TYPE val); // Change the size of the current vector to size and assign val to the newly created element
  • The difference between resize and reserve

    • Reserve is reserved space in the container, but does not actually create the element object. Before creating the object, you cannot refer to the elements in the container, so when adding new elements, you need to use push_back()/insert()
    • Resize changes the size of the container and creates the object. Therefore, after calling this function, you can refer to the object in the container. So when adding a new object, use the operator[] operator, or use an iterator to refer to the element object.
    • Resize means to reallocate the size, and reserve means to reserve some space
    • Attached: Reverse and resize interface source code
    void resize(size_type new_size){ resize(new_size, T()); }void resize(size_type new_size, const & x){
    	if(new_size < oldsize)
    		erase(oldbegin + new_size, oldend);  // erase the data outside the range to ensure that the data outside the range is invalid
    	else
    		insert(oldend, new size - oldsize, x);  // Fill the data of the gap within the interval to ensure the validity of the data within the interval
    Copy the code
    • case
    #include <iostream>
    #include <vector> 
    using namespace std;
    
    int main(a) {
        vector<int> v;
        
        for(int i = 1; i <= 3; i ++)
            v.push_back(i);
            
        v.resize(5.8);   // The two extra Spaces are initialized to 8
        for(int i = 0; i < v.size(); i ++)  // Resize and reverse do not delete the original elements to free up space
            cout<<v[i];
        cout<<endl;
        
        v.reserve(7);  // The new element has not yet been constructed
        for(int i = 0; i < 7; i ++)
            cout<<v[i]<<"";  // When I > 4. The element cannot be accessed with [] at this time
        cout<<endl;
        
        cout<<v.size()<<endl;
        cout<<v.capacity()<<endl;
        return 0;
    
    }
    Copy the code
    12388 12388 0 0 5 7Copy the code
  • The size function

    • Grammar:
      • size_type size(); // Return the number of elements in the current vector
  • Swap function

    • Grammar:
      • void swap(vector & from); // Swap the elements of the current vector with those of vector from
    • case
    #include <iostream>
    #include <vector> 
    using namespace std;
    
    int main(a) {
        vector<int> v1, v2;
        
        for(int i = 1; i <= 3; i ++){
            v1.push_back(i);
            v2.push_back(i);
        }
        
        v2.push_back(4);
        v2.push_back(5);
        v1.swap(v2);
        
        for(int j = 0; j < v1.size(); j ++)
            cout<<v1[j]<<"";
        cout<<endl;
        
        for(int k = 0; k < v2.size(); k ++)
            cout<<v2[k]<<"";
        cout<<endl;
        
        return 0;
    
    }
    Copy the code
    One, two, three, four, five, one, two, threeCopy the code

Use the vector

  • Vector basic usage case
	#include <iostream>
	#include <vector> 
	using namespace std;
	
	template<class T>
	void PrintVector(const vector <T> & v)
	{
	    // A template to print all the elements in the vector
	    typename vector <T>::const_iterator i;  // An iterator of type const_iterator can only be read and cannot be overridden
	    // Typename indicates that vector
      
       ::const_iterator is a type, which can be left unwritten in VS
      
	    for(i = v.begin(); i ! = v.end(); i ++)cout<<*i<<"";
	    cout<<endl;
	}
	
	int main(a)
	{
	    int a[5] = {1.2.3.4.5};
	    vector<int> v(a, a + 5);  // Put the contents of array a into v
	    cout<<"1."<<v.end() - v.begin()<<endl;  // Two random iterators can be subtracted
	    cout<<"2."; PrintVector(v);
	    v.insert(v.begin() + 2.13);  // Insert 13 at begin() + 2
	    cout<<"3."; PrintVector(v);
	    v.erase(v.begin() + 2);  // Delete the element at begin() + 2
	    cout<<"4."; PrintVector(v);
	    vector<int> v2(4.100);  V2 has four elements, each of which is 100
	    v2.insert(v2.begin(), v.begin() + 1, v.begin() + 3);  // Insert part of v at the beginning of v2
	    cout<<"5. v2: "; PrintVector(v2);
	    v.erase(v.begin() + 1, v.begin() + 3);  // delete a interval on v, i.e. [2, 3]
	    cout<<"6."; PrintVector(v);
	    
	    return 0;
	}
Copy the code
	1. 5
	2. 1 2 3 4 5 
	3. 1 2 13 3 4 5 
	4. 1 2 3 4 5 
	5. v2: 2 3 100 100 100 100 
	6. 1 4 5 
Copy the code
  • Vectors can also be nested to form variable-length two-dimensional arrays
	#include <iostream>
	#include <vector> 
	using namespace std;
	
	int main(a)
	{
	    vector<vector<int> > v(3);  // v3 has three elements, each of which is a vector
	    for(int i = 0; i < v.size(); i ++)
	        for(int j = 0; j < 4; j ++)
	            v[i].push_back(j);
	        
	    for(int i = 0; i < v.size(); i ++){
	        for(int j = 0; j < v[i].size(); j ++)
	            cout<<v[i][j]<<"";
	        cout<<endl;
	    }
	    return 0;
	}
Copy the code
0 1 2 3 0 1 2 3 0 1 2 3 0 1 2 3 V defines a vector in which each element is a vector<int>, that is, we can think of v as a two-dimensional array with three lines, each of which is a variable length one-dimensional array - in Dev C++, There should be a space between the two '>' after int, otherwise some compilers will treat them as' >> 'operators, and the compilation will failCopy the code
  • A vector can be not only an int, a double, or a string. It can also be a structure, but note that the structure is defined asglobal, or it will make a mistake
    • case
    #include <iostream>
    #include <stdio.h>
    #include <algorithm>
    #include <vector> 
    using namespace std;
    
    typedef struct rect{
        int id;
        int length;
        int width;
        
        // Is a structure for vector elements. You can define a comparison function inside the structure, which is sorted in ascending order by ID, length, and width
        bool operator < (const rect & a) const
        {
            if(id ! = a.id)return id < a.id;
            else
            {
                if(length ! = a.length)return length < a.length;
                else
                    return width < a.width;
            }
        }
    }Rect;
    
    int main(a) {
        vector<Rect> vec;
        Rect rect;
        rect.id = 1;
        rect.length = 2;
        rect.width = 3;
        vec.push_back(rect);
        vector<Rect>::iterator it = vec.begin();
        cout<<(*it).id<<""<<(*it).length<<""<<(*it).width<<endl;
        
        return 0;
    }
    Copy the code
      	1 2 3
    Copy the code