Usage of Vector in C ++ knowledge

Source: Internet
Author: User

The built-in arrays in C ++ support the container mechanism, but they do not support the abstract semantics of containers. To solve this problem, we need to implement such a class. In standard C ++, container vector is used. The container vector is also a class template.
Use the header file # include <vector> for the vector type of the standard library. Vector is a class template. Vector <int> is a data type. The storage space of the Vector is continuous, and the list is not continuously stored.

I. Definition and initialization
Vector <typeName> v1; // v1 is empty by default. Therefore, the following assignment is incorrect. v1 [0] = 5;
Vector <typeName> v2 (v1); or v2 = v1; or vector <typeName> v2 (v1.begin (), v1.end (); // v2 is a copy of v1, if v1.size ()> v2.size () is assigned, v2.size () is expanded to v1.size ().
Vector <typeName> v3 (n, I); // v3 contains n typeName elements whose values are I.
Vector <typeName> v4 (n); // v4 contains n elements whose values are 0.
Int a [4] = {0, 1, 2, 3}; vector <int> v5 (a, a + 5); // The v5 size is 5, v5 is initialized to 5 values of. The next Pointer Points to the next position of the last element to be copied.
Vector <int> v6 (v5); // v6 is a copy of v5.
Vector <type> identifier (maximum capacity, all initial values );

 

Ii. Value Initialization
1> if no element initialization formula is specified, the standard library provides an initialization value for value initialization.
2> If the saved expression contains elements of the class type of the constructor, the standard library uses this type of constructor for initialization.
3> If the saved expression does not have the class elements of the constructor, the Standard Library generates an object with an initial value and uses this object for value initialization.


Iii. Most important operations of vector objects
1. v. push_back (t) adds t data at the end of the container, and the container size increases.
In addition, the list has the push_front () function. When inserted at the front end, the element subscript increases sequentially.
2. v. size () returns the number of data in the container, and size returns the size_type value defined by the corresponding vector class. V. resize (2 * v. size) or

V. resize (2 * v. size, 99) doubles the capacity of v (and initializes the value of the new element to 99)
3. v. empty () determines whether the vector is empty.
4. v [n] returns the element whose position is n in v.
5. v. insert (pointer, number, content) inserts the content of the number of content at the position pointed to by pointer in v.
And v. insert (pointer, content), v. insert (pointer, a [2], a [4]) to insert three elements from a [2] to a [4.
6. v. pop_back () deletes the last element of the container and does not return this element.
7. v. erase (pointer1, pointer2) deletes the elements from pointer1 to pointer2 (including the elements referred to by pointer1.
After deleting an element in the vector, all elements after this position need to move forward to a position, although the current iterator position does not automatically add 1,
However, due to the sequential forward of subsequent elements, it is equivalent to automatically pointing to the next position of the iterator.
8. v1 = v2: Determine whether v1 and v2 are equal.
9 .! =, <, <=,>,> = Keep the meanings of these operators.
10. vector <typeName>: iterator p = v1.begin (); the initial value of p points to the first element of v1. * P indicates the value of the element to which it points.
For const vector, <typeName> can only be accessed using a pointer of the vector <typeName>: const_iterator type.
11. p = v1.end (); p points to the next position of the last element of v1.
12. v. clear () delete all elements in the container. 12. v. clear () delete all elements in the container.

# Include functional algorithms in <algorithm>
Search algorithms: find (), search (), count (), find_if (), search_if (), count_if ()
Sort by category: sort (), merge ()
Delete algorithms: unique () and remove ()
Generation and variation: generate (), fill (), transformation (), copy ()
Relational algorithms: equal (), min (), max ()
Sort (v1.begin (), vi. begin () + v1.size/2); sorts the elements in the First Half of v1.
List <char>: iterator pMiddle = find (cList. begin (), cList. end (), 'A'); if it is found, the pointer appears for the first time in the queried content; otherwise, end () is returned ().
Vector <typeName >:: size_type x; vector <typeName> type count, which can be used for loops like for (int I)


Programmers who are new to C ++ may think that the subscript operation of vector can add elements, but it is not:

Vector <int> ivec; // empty vector

For (vector <int >:: size_type ix = 0; ix! = 10; ++ ix)

Ivec [ix] = ix; // disaster: ivec has no elements

The above program tries to insert 10 new elements in ivec, And the element values are integers ranging from 0 to 9. However, ivec is an empty vector object, and the subscript can only be used to obtain existing elements.

The correct statement of this loop should be:

For (vector <int >:: size_type ix = 0; ix! = 10; ++ ix)

Ivec. push_back (ix); // OK: adds new element with value ix


Warning only an existing element can be indexed using the subscript operator. When values are assigned through subscript operations, no elements are added. Only subscripts can be performed on elements that are known to exist.

Iv. memory management and efficiency

1. Use the reserve () function to set the capacity in advance to avoid inefficiency caused by multiple capacity expansion operations.

One of the most commendable features of STL containers is that they can automatically grow to be enough to accommodate the data you put in as long as they do not exceed their maximum size. (To know the maximum value, you only need to call the member function named max_size .) For vector and string, if more space is needed, increase the size in a way similar to realloc. The vector container supports random access. Therefore, to improve efficiency, it uses dynamic arrays internally. When applying for a specific size through reserve (), the internal buffer is always increased by exponential boundary. When adding elements such as insert or push_back, if the memory of the dynamic array is insufficient at this time, it is necessary to dynamically re-allocate the current size of 1.5 ~ 2 times the new memory zone, and then copy the content of the original array. Therefore, in general, the access speed is the same as that of the general array, and its performance will decrease only when reallocation occurs. As the code above tells you. In the pop_back operation, capacity does not decrease because the elements in the vector container are reduced, and the size before the operation is maintained. For a vector container, if a large amount of data requires push_back, you should use the reserve () function to set its capacity in advance. Otherwise, many capacity expansion operations may occur, resulting in low efficiency.

The reserve member function allows you to minimize the number of times that must be re-allocated, so you can avoid overhead of true allocation and expiration of iterator/pointer/reference. But before I explain why reserve can do that, let me briefly introduce the four sometimes confusing member functions. In standard containers, only vector and string provide all these functions.

(1) size () indicates the number of elements in the container. It does not tell you how much memory the container has allocated to its elements.
(2) capacity () tells you how many elements the container can accommodate in its allocated memory. That is how many elements the container can accommodate in that memory, rather than how many elements it can accommodate. If you want to know how much memory is not occupied in a vector or string, you must subtract size () from capacity (). If size and capacity return the same value, there is no space left in the container, and the next insertion (through insert or push_back) will lead to the above re-allocation step.
(3) resize (Container: size_type n) forces the Container to accommodate n elements. After resize is called, size returns n. If n is smaller than the current size, the elements at the end of the container are destroyed. If n is greater than the current size, the new default element is added to the tail of the container. If n is greater than the current capacity, it will be reassigned before the element is added.
(4) reserve (Container: size_type n) forces the Container to change its capacity to at least n, and the provided n is not smaller than the current size. This forces a redistribution because the capacity needs to increase. (If n is smaller than the current capacity, vector ignores it. This call does nothing. string may reduce its capacity to size () and n in large numbers, however, the size of the string is not changed. In my experience, it is generally better to use reserve to Trim excess capacity from a string than to use "exchange skills", which is the subject of Clause 17 .)

This introduction indicates that as long as there are elements to be inserted and the container capacity is insufficient, they will be re-allocated (including the original memory allocated and recycled they maintain, object copy and analysis structure and iterator, pointer and reference failure ). Therefore, the key to avoiding reallocation is to use reserve to set the container capacity to large enough as soon as possible. It is best to do so immediately after the container is constructed.

For example, suppose you want to create a vector containing 1-values <int>. If reserve is not used, you can do it like this:

Vector <int> v;
For (int I = 1; I <= 1000; ++ I) v. push_back (I );
In most STL implementations, this code will cause two to ten Re-allocations during the loop process. (10 is nothing strange. Remember that when the redistribution happens, the vector generally doubles the capacity, and 1000 is about 210 .)

Change the code to use reserve. We get this:

Vector <int> v;
V. reserve (1000 );
For (int I = 1; I <= 1000; ++ I) v. push_back (I );
This will not happen in the loop.

The relationship between size and capacity allows us to predict when insertion will cause the vector or string to be re-allocated, and, it can be predicted when insertion will invalidate the iterator, pointer, and reference pointing to the container. For example, the following code is provided,

String s;
...
If (s. size () <s. capacity ()){
S. push_back ('x ');
}
Push_back does not invalidate the iterator, pointer, or reference pointing to this string, because the size of the string must be greater than its size. If push_back is not executed and the code performs an insert operation at any position of the string, we can still ensure that no redistribution occurs during the insertion. However, it is consistent with the general rule that the iterator becomes invalid when it is inserted with string. All iterators, pointers, and references from the inserted position to the end of the string will become invalid.

Back to the purpose of these terms, reserve is usually used in two cases to avoid unnecessary redistribution. The first available scenario is when you know exactly or approximately how many elements will last in the container. In that case, just like the vector code above, you just reserve the appropriate amount of space in advance. The second case is to keep the maximum space you may need, and then, once you add full data, trim any excess capacity.

2. Use swap techniques to Trim excess space/memory of a vector

There is a way to reduce it from its largest capacity to its current capacity. This method of capacity reduction is often called "shrink to fit )". This method only requires one statement: vector <int> (ivec). swap (ivec );
Expression vector <int> (ivec) creates a temporary vector, which is a copy of ivec: The copy constructor of the vector. However, the copy constructor of the vector only allocates the memory required for the copied elements, so this temporary vector has no additional capacity. Then we have the temporary vector and ivec exchange data, and now we have done it. ivec only has the capacity that the temporary variable has been trimmed, this temporary variable holds the excess capacity that was never used in ivec. Here (the end of this statement), the temporary vector is destroyed, so the memory used by ivec is released and reduced to the appropriate one.

3. Use the swap method to forcibly release memory occupied by STL Vector

Template <class T> void ClearVector (vector <T> & v)
{
Vector <T> vtTemp;
VtTemp. swap (v );
}
For example
Vector <int> v;
Nums. push_back (1 );
Nums. push_back (3 );
Nums. push_back (2 );
Nums. push_back (4 );
Vector <int> (). swap (v );

/* Or v. swap (vector <int> ());*/

/* Or {std: vector <int> tmp = v; v. swap (tmp) ;}; // Add braces {} to enable automatic structure analysis when tmp exits */

 

5. Testing the behavior of Vector memory management member functions
The C ++ STL vector is widely used, but there have been many guesses about its memory management model. The following uses the instance code test to learn about its memory management method. The test code is as follows:

# Include <iostream>
# Include <vector>
Using namespace std;

Int main ()
{
Vector <int> iVec;
Cout <"container size:" <iVec. size () <endl;
Cout <"container capacity:" <iVec. capacity () <endl; // 1 element, container capacity is 1

IVec. push_back (1 );
Cout <"container size:" <iVec. size () <endl;
Cout <"container capacity:" <iVec. capacity () <endl; // two elements, container capacity 2

IVec. push_back (2 );
Cout <"container size:" <iVec. size () <endl;
Cout <"container capacity:" <iVec. capacity () <endl; // three elements, container capacity: 4

IVec. push_back (3 );
Cout <"container size:" <iVec. size () <endl;
Cout <"container capacity:" <iVec. capacity () <endl; // four elements, container capacity: 4

IVec. push_back (4 );
IVec. push_back (5 );
Cout <"container size:" <iVec. size () <endl;
Cout <"container capacity:" <iVec. capacity () <endl; // five elements, container capacity is 8

IVec. push_back (6 );
Cout <"container size:" <iVec. size () <endl;
Cout <"container capacity:" <iVec. capacity () <endl; // six elements, container capacity: 8

IVec. push_back (7 );
Cout <"container size:" <iVec. size () <endl;
Cout <"container capacity:" <iVec. capacity () <endl; // seven elements, container capacity: 8

IVec. push_back (8 );
Cout <"container size:" <iVec. size () <endl;
Cout <"container capacity:" <iVec. capacity () <endl; // 8 elements, container capacity is 8

IVec. push_back (9 );
Cout <"container size:" <iVec. size () <endl;
Cout <"container capacity:" <iVec. capacity () <endl; // nine elements, container capacity: 16
/* Vs2005/8 does not double the capacity growth, as shown in figure
Capacity of 9 elements 9
Capacity of 10 elements 13 */

/* Test the special swap () switching function in objective stl ()*/
Cout <"the current vector size is:" <iVec. size () <endl;
Cout <"current vector capacity:" <iVec. capacity () <endl;
Vector <int> (iVec). swap (iVec );

Cout <"temporary vector <int> object size:" <(vector <int> (iVec). size () <endl;
Cout <"temporary vector <int> Object capacity:" <(vector <int> (iVec). capacity () <endl;
After cout <"is switched, the current vector size is:" <iVec. size () <endl;
After cout <"is switched, the current vector capacity is:" <iVec. capacity () <endl;

Return 0;
}

 

6. other vector member functions

C. assign (beg, end)
Assign the value of the data in the [beg; end) interval to c.
C. assign (n, elem)
Assign a copy of n elem values to c.
C. at (idx)
Returns the data indicated by the index idx. If idx is out of bounds, out_of_range is thrown.
C. back ()
Returns the last data and does not check whether the data exists.
C. front ()
Return a data record.
Get_allocator
Returns a copy using the constructor.
C. rbegin ()
Returns the first data of a reverse queue.
C. rend ()
Returns the next location of the last data in a reverse queue.
C .~ Vector <Elem> ()
Destroys all data and releases memory.

Share: 

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.