C++:vector of the use of the explanation (reproduced)

Source: Internet
Author: User

Original address:http://blog.csdn.net/hancunai0017/article/details/7032383

Vector: A data structure in C + +, exactly a class. It is equivalent to a dynamic array, and when the programmer is unable to know the size of the array that he needs, it can be used to solve the problem to achieve the maximum space savings.

Usage:

1. The file contains:

First, add #include<vector> at the beginning of the program to include the required class file vector

Also must be added using namespace std;

2. Variable declaration:

2.1 Example: declaring an int vector instead of one-dimensional array: vector <int> A; (equal to declaring an int array a[], the size is not specified, can be dynamically added to the inside of the delete).

2.2 Example: vector instead of two-dimensional array. In fact, just declare a one-dimensional array vector, and an array of names actually represents its first address, so just declare a vector of the address, that is: vector <int *> A. Same as ideal vectors instead of three-dimensional arrays , Vector <int**>a; go up and so on.

3. Specific usage and function calls:

3.1 How do I get the elements in a vector? Its usage and array:

For example:

Vector <int *> A

int b = 5;

A.push_back (b);//The function is detailed below

cout<<a[0]; Output is 5

1.push_back add a data at the end of the array
2.pop_back remove the last data from the array
3.at get the data of the numbered position
4.begin get pointer to array header
5.end gets the pointer to the last cell +1 of the array
6. Front getting a reference to the array header
7.back get a reference to the last cell of the array
8.max_size get vector max can be how big
9.capacity the size of the current vector allocation
10.size size of current usage data
11.resize changes the current size of the data used, if it is larger than the current use, the default value is populated
12.reserve changes the size of the space allocated by the current VECOTR
13.erase Delete the data item that the pointer points to
14.clear empty the current vector
15.rbegin returns the starting pointer after the vector reversal (actually the original end-1)
16.rend returns the end pointer of the vector reversal (actually the original begin-1)
17.empty determine if the vector is empty
18.swap exchanging data with another vector

3.2 Detailed function implementation function: where Vector<int> c.

C.clear () Removes all data from the container.

C.empty () Determines whether the container is empty.

C.erase (POS) Delete data at the POS location

C.erase (beg,end) Delete data from [Beg,end] Interval

C.front () returns the first data.

C.insert (Pos,elem) inserts a elem copy at POS location

C.pop_back () deletes the last data.

C.push_back (elem) adds a data to the tail.

C.resize (num) to reset the size of the container

C.size () returns the number of actual data in the container.

C.begin () returns an iterator that points to the first element of the container

C.end () returns an iterator that points to the last element of the container


4. Memory management and efficiency

1. Use the reserve () function to set the size of the capacity ahead of time to avoid multiple capacity expansion operations resulting in inefficiency.

One of the most admirable features about STL containers is that they can automatically grow to accommodate the data you put in as long as they don't exceed their maximum size. (To know this maximum value, just call the member function called Max_size.) For vectors and strings, if more space is needed, it grows in size like realloc thought. The vector container supports random access, so in order to improve efficiency, it is implemented internally using dynamic arrays. When you request a specific size by reserve (), it always increases its internal buffer by exponential bounds. When adding elements such as insert or push_back, if the memory of the dynamic array is not enough, it is necessary to dynamically reassign the new memory area of the current size 1.5~2 times, and then copy the contents of the original array into the past. Therefore, in general, its access speed is the same as the general array, only when the reallocation occurs, its performance will be degraded. As the above code tells you. In the case of pop_back operations, the capacity does not decrease due to the decrease in the elements in the vector container, but also maintains the size before the operation. For vector containers, if there is a large amount of data to be push_back, the reserve () function should be used to set its capacity in advance, otherwise there will be many sub-capacity expansion operations, resulting in inefficient.

The reserve member function allows you to minimize the number of re-allocations that must be made, thus avoiding the overhead of true allocations and invalidation of iterators/pointers/references. But before I explain why reserve can do that, let me briefly describe some of the four related member functions that are sometimes confusing. In a standard container, only the vector and string provide all of these functions.

(1) Size () tells you how many elements are in the container. It does not tell you how much memory the container allocates for the elements it holds.
(2) capacity () tells you how many elements the container can hold in the memory it has allocated. That's how many elements a container can hold in that memory, rather than how many elements it can hold. 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 (via insert or push_back, etc.) will cause the above redistribution step.
(3) Resize (container::size_type N) forcibly changes the container to accommodate n elements. After calling resize, size will return N. If n is less than the current size, the element at the end of the container is destroyed. If n is greater than the current size, the new default constructed element is added to the container trailer. If n is greater than the current capacity, redistribution occurs before the element is added.
(4) reserve (Container::size_type N) forces the container to change its capacity to at least N, providing n not less than the current size. This generally forces a redistribution, as capacity needs to be increased. (if n is less than the current capacity, the vector ignores it, and the call does nothing, and the string may reduce its capacity to size () and the large number in N, but the size of the string does not change.) In my experience, using the reserve to trim excess capacity from a string is generally not as good as using the "swap technique", which is the subject of clause 17. )

This profile indicates that redistribution occurs whenever there are elements that need to be inserted and the capacity of the container is insufficient (including the raw memory allocations and recoveries they maintain, the copying and destruction of objects and the invalidation of iterators, pointers, and references). Therefore, the key to avoid redistribution is to use reserve as soon as possible to set the container capacity is large enough, preferably after the container is constructed immediately.

For example, suppose you want to create a vector<int> that holds 1-1000 values. Instead of using reserve, you can do it like this:

Vector<int> v;
for (int i = 1; I <=, ++i) v.push_back (i);
In most STL implementations, this code will cause 2 to 10 reallocation during the loop. (10 This number is nothing strange.) Remember that vectors tend to double the capacity at the time of redistribution, and 1000 is approximately equal to 210. )

To change the code to use reserve, we get this:

Vector<int> v;
V.reserve (1000);
for (int i = 1; I <=, ++i) v.push_back (i);
This does not occur in the loop redistribution.

The relationship between size and capacity allows us to predict when the insertion will cause a vector or string to be reassigned, and to predict when the insertion will invalidate iterators, pointers, and references in the container. For example, given this code,

string S;
...
if (S.size () < s.capacity ()) {
S.push_back (' x ');
}
The push_back call does not invalidate the iterator, pointer, or reference that points to the string, because the capacity of the string is guaranteed to be greater than its size. If Push_back is not executed, the code makes an insert anywhere in the string, and we can still guarantee that no redistribution occurs during the insertion, but consistent with the general rule that the iterator fails when the string is inserted. All iterators/pointers/references from the insertion position to the end of the string will be invalidated.

Back to the main thrust of this article, there are usually two cases where the reserve is used to avoid unnecessary redistribution. The first available case is when you know exactly or about how many elements will eventually appear in the container. In that case, just like the vector code above, you just reserve an appropriate amount of space in advance. The second case is to keep the maximum space you may need, and then, once you've added all the data, trim out any excess capacity.

2. Use "switching technique" to trim vector excess space/memory

There is a way to reduce it from the once-largest capacity to the capacity it now needs. This way of reducing capacity is often referred to as "Shrinking to fit" (shrink to fit). The method requires only one statement:vector<int> (IVEC). Swap (IVEC);
The expression vector<int> (Ivec) establishes a temporary vector, which is a copy of the Ivec: the copy constructor of the vector does the work. However, the vector's copy constructor allocates only the memory required for the copied elements, so this temporary vector has no extra capacity. Then we let the temporary vector and the Ivec exchange data, when we finished, Ivec only the temporary variable of the trimmed capacity, and this temporary variable holds the unused excess capacity that was once in the Ivec. Here (at the end of this statement), the temporary vector is destroyed, so the memory used by the previous Ivec is freed and shrunk to fit.

3 "Using the Swap method to forcibly release the memory of the STL vector

template < class t> void Clearvector (vector<t>& v)
{
vector<t>vttemp;
Vttemp.swap (v);
}
Such as
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); }; The brace {} is automatically refactored when TMP exits {} */

Behavior test for 5.Vector memory management member functions

The vector of C + + STL is very widely used, but the management model of its memory has been a lot of guesses, the following example code test to understand 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 elements with a container capacity of 1

Ivec.push_back (1);
cout << "container size:" << ivec.size () << Endl;
cout << "Container capacity:" << ivec.capacity () << Endl; 2 elements with a container capacity of 2

Ivec.push_back (2);
cout << "container size:" << ivec.size () << Endl;
cout << "Container capacity:" << ivec.capacity () << Endl; 3 elements with a container capacity of 4

Ivec.push_back (3);
cout << "container size:" << ivec.size () << Endl;
cout << "Container capacity:" << ivec.capacity () << Endl; 4 Elements with a container capacity of 4

Ivec.push_back (4);
Ivec.push_back (5);
cout << "container size:" << ivec.size () << Endl;
cout << "Container capacity:" << ivec.capacity () << Endl; 5 Elements with a container capacity of 8

Ivec.push_back (6);
cout << "container size:" << ivec.size () << Endl;
cout << "Container capacity:" << ivec.capacity () << Endl; 6 elements with a container capacity of 8

Ivec.push_back (7);
cout << "container size:" << ivec.size () << Endl;
cout << "Container capacity:" << ivec.capacity () << Endl; 7 elements with a container capacity of 8

Ivec.push_back (8);
cout << "container size:" << ivec.size () << Endl;
cout << "Container capacity:" << ivec.capacity () << Endl; 8 elements with a container capacity of 8

Ivec.push_back (9);
cout << "container size:" << ivec.size () << Endl;
cout << "Container capacity:" << ivec.capacity () << Endl; 9 elements with a container capacity of 16
/* VS2005/8 capacity growth is not doubled, such as
9 Element Capacity 9
10 Elements Capacity 13 */

/* Test the Special Swap Swap () in the effective STL */
cout << "The size of the current vector is:" << ivec.size () << Endl;
cout << "Current vector capacity:" << ivec.capacity () << Endl;
Vector<int> (IVEC). Swap (IVEC);

cout << "The size of the temporary vector<int> object is:" << (vector<int> (IVEC)). Size () << Endl;
cout << "The capacity of the temporary Vector<int> object is:" << (vector<int> (IVEC)). Capacity () << Endl;
cout << "After swapping, the current vector size is:" << ivec.size () << Endl;
cout << "After swapping, the current vector capacity is:" << ivec.capacity () << Endl;

return 0;
}

Other member functions of 6.vector

C.assign (beg,end): Assigns the data in the [beg; end] Interval to C.
C.assign (N,elem): Assigns a copy of n elem to C.
c.at (IDX): Returns the index IDX refers to the data, if the IDX is out of bounds, throws Out_of_range.
C.back (): Returns the last data without checking if the data exists.
C.front (): Returns a data back to the ground.
Get_allocator: Returns a copy using the constructor.
C.rbegin (): Returns the first data for a reverse queue.
C.rend (): Returns the next position of the last data in a reverse queue.
c.~ Vector <Elem> (): Destroys all data and frees up memory.

7. Remarks: In the course of using vectors, we hereby list the following issues:

1)

Vector <int > A;

int b = 5;

A.push_back (b);

The value of a[0] will not be affected if you assign another value to B

2)

Vector <int*> A;
int *b;
b= New Int[4];
b[0]=0;
B[1]=1;
b[2]=2;
A.push_back (b);
Delete B; Release B's Address space
for (int i=0; I <3; i++)
{
cout<<a[0][i]<<endl;
}

At this point the output value is not the value initialized by the first B array, but some unpredictable value.

Analysis: Based on 1) 2) results, it can be thought that in 1, the value of B is pressed into the a vector, that is, A[0]=b, at which point A[0] and b are stored in two different addresses. Therefore, changing the value of B does not affect a[0], and in 2), because it is to push an address (pointer) into the vector A, that is a[0 ]=b, so releasing the address of B also frees the address of a[0], so the values stored in the a[0] array are unknown.

C++:vector of the use of the explanation (reproduced)

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.