Vector in C + + is a very flexible array, it can automatically expand the size to accommodate the new elements, but also can quickly index the stored elements, however, this use of convenience is also a cost, because the vector's underlying data structure is really an array, just encapsulated some convenient operation, Like Push_back (), reserve () and so on, let's take a look at the behavior behind these simple operations, in order to illustrate the problem, we define a class and output some information in its constructor, the class is defined as follows:
Class A {static int i;public:int ID; A () {id = i++;cout<< "a:constructor" <<ENDL;} A (const a&) {id = i++;cout<< "a:copy constructor" <<ENDL;} ~a () {cout<< "A:destructor" <<endl;}}; int a::i = 0;
This class has a default constructor, a copy constructor, and a destructor, and while we try to give an ID to each object of a, first look at the simplest use of vectors: Define a vector:
Vector<a> v1 (2);cout<< "ID of the 1st element:" <<v1[0].id<<endl;cout<< "ID of the 1ND Element: "<<v1[1].id<<endl;
When defining v1, we default it to save two objects, and the output of the program is as follows:
A:constructor
A:copy Constructor
A:copy Constructor
A:destructor
ID of the 1st element:1
ID of the 2nd element:2
A:destructor
A:destructor
As you can see, in the definition of V1, a total of 1 default constructors and 2 copy constructors are called, and after the definition, 2 objects are stored in V1, and their IDs are 1, 2, which means that 2 objects in V1 are obtained by copy constructors, so who is the copy? Of course, the temporary object generated by the default constructor is called, and the temporary object is refactored after the V1 is defined, so a message called by the destructor is printed before the output ID. Here's another way to define it:
Vector<a> V1;v1.reserve (2);cout<< "ID of the 1st element:" <<v1[0].id<<endl;cout<< "ID of The 1nd element: <<v1[1].id<<endl;
Here we reserve two objects of storage space for V1, with the following output:
ID of the 1st element:0
ID of the 2nd element:0
As you can see, in this case, 2 objects are not automatically constructed and saved in V1, but we are also lucky to be able to manipulate the two objects, although these two operations are meaningless. Let's take a look at how reserve () Reserves storage space:
Vector<a> v1 (2); V1.reserve (3);
The output results are as follows:
#1 A:constructor
#2 A:copy Constructor
#3 A:copy Constructor
#4 A:destructor
#5 A:copy Constructor
#6 A:copy Constructor
#7 A:destructor
#8 A:destructor
#9 A:destructor
#10 A:destructor
We can count the number of constructors, the first three constructors in our expectation, but with the reserve call, we call two copy constructors, because the reserve has made a larger array for us and tried to put the contents of the original array into the new array, After that the original array will be deleted, this can also be from the # Two, #8两行的析构函数可以看出来 (destruction of the original array of v1), so the size of the change is not as simple as it is used, it is possible to trigger a lot of tectonic destruction operations. Let's look at an example below:
A a;vector<a> v1;v1.reserve (2); V1.push_back (a); V1.push_back (a); V1.push_back (a);
In this example, you begin to reserve 2 objects for V1, but then insert 3 objects to see what the output is:
A:constructor
A:copy Constructor
A:copy Constructor
A:copy Constructor
A:copy Constructor
A:copy Constructor
A:destructor
A:destructor
A:destructor
A:destructor
A:destructor
A:destructor
As you can see, a total of 5 copy constructors are called! The first two good understanding, is accompanied by the first two push_back and was called, but the third push_back time, because the space in the V1 is not enough, so re-set the number of groups, first the original array of two objects copied over, and then the third object push into the new array, So the third Push_back throws 3 copy constructors, and of course an additional two destructors, so the vector is useful, but sometimes it can trigger a lot of memory allocations and tectonic destructors, and if the application is sensitive to this, consider other containers, like list.
The internal behavior of C++:vector