If you see the definition of push_back
of the vector:
// [23.2.4.3] modifiers
/**
* @brief Add data to the end of the %vector.
* @param __x Data to be added.
*
* This is a typical stack operation. The function creates an
* element at the end of the %vector and assigns the given data
* to it. Due to the nature of a %vector this operation can be
* done in constant time if the %vector has preallocated space
* available.
*/
void
push_back(const value_type& __x)
{
if (this->_M_impl._M_finish != this->_M_impl._M_end_of_storage)
{
_Alloc_traits::construct(this->_M_impl, this->_M_impl._M_finish,
__x);
++this->_M_impl._M_finish;
}
else
#if __cplusplus >= 201103L
_M_emplace_back_aux(__x);
#else
_M_insert_aux(end(), __x);
#endif
}
#if __cplusplus >= 201103L
void
push_back(value_type&& __x)
{
emplace_back(std::move(__x));
}
#endif
Here it is easy to see what is push_back
doing:
- In older standards (less than C++11) it just passes an object by copy thus vector creates a copy of the object you passed to the
push_back
.
- In newer standards (>= C++11) it simply uses move-constructor which avoids the copying but still creates an object by using move-constructor.
To avoid this you may use the emplace_back
:
class A {
public:
A(int i = 0) { cout << "A ctor" << endl; }
~A() { cout << "A dtor" << endl; }
};
int main() {
vector<A> v;
cout << "after vector created" << endl;
v.emplace_back();
cout << "after one A added" << endl;
}
This will just create an object of class A
inside vector's memory space by passing an arguments of the method to the constructor of the class object, so it would not be copied or moved:
after vector created
A ctor
after one A added
A dtor
Test emplace_back
P.S. About what you got:
after vector created
A ctor
A dtor
after one A added
A dtor
You don't see ctor-dtor paired here because in std::vector::push_back
as I mentioned above does not construct an object of class A through the default constructor (in which you print A ctor
) but a copy-constructor or a move-constructor (depends on a standard with what you compile and implementation details).
So, it is actually paired but you just don't see it because you did not implement (override implicitly-declared) move and copy constructors. If you'll do this, you'll see something like this:
A default constructor
A copy/move constructor
A destructor
A destructor