DavidY
DavidY

Reputation: 425

How constructors / destructors are used when creating / adding objects to a container

I am trying to learn how the constructors / destruction are used when creating and adding objects to a container. For the XClass in the example below, a simple constructor, a copy constructor, a move constructor, and a destructor are implemented:

std::vector<XClass> v;
    v.push_back(XClass(1));
    v.push_back(XClass(2));

I used console to track how the constructors and destructors are called, below is what I got. The message "with argument x" refers to the argument passed in when constructing the object. When it's 1 it refers to the first object XClass(1), and similarly for XCLass(2). The destructor is called with 0 because the object had been initialized by the move constructor.

1.simple constructor called with argument 1.
2.move constructor called with argument 1.
3.destructor called with argument 0.
4.simple constructor called with argument 2.
5.move constructor called with argument 2.
6.copy constructor called with argument 1.
7.destructor called with argument 1.
8.destructor called with argument 0.

I can understand all the lines except 6 and 7. the first object is created and added through line 1 to 3. The second object is created and added with line 4, 5, and 8. Why do we need to copy object and destruct it again at line 6 and 7, especially considering we are adding the second object to the back without moving the first one?

Upvotes: 1

Views: 81

Answers (1)

songyuanyao
songyuanyao

Reputation: 172964

especially considering we are adding the second object to the back without moving the first one?

The 1st element is moved in another style here.

For std::vector::push_back, when the new size() is greater than capacity() the reallocation happens to extend the storage capacity.

The storage of the vector is handled automatically, being expanded and contracted as needed. Vectors usually occupy more space than static arrays, because more memory is allocated to handle future growth. This way a vector does not need to reallocate each time an element is inserted, but only when the additional memory is exhausted. The total amount of allocated memory can be queried using capacity() function.

When it happens std::vector will allocate the new inner buffer, and copy all the existing elements into the new buffer, then destroy them and deallocate the old inner buffer. That's why you see one copy construction and destruction.

You can reserve the storage capacity via std::vector::reserve to avoid reallocation, e.g.

std::vector<XClass> v;
v.reserve(2);
v.push_back(XClass(1));
v.push_back(XClass(2));

Then you won't see additional copy construction and destruction.

Upvotes: 3

Related Questions