Чтобы ясно видеть, что происходит, я рекомендую включить указатель this
в вывод, чтобы определить, какой A вызывает метод.
A() {cout<<"A (" << this << ") Construction" <<endl;}
A(A const& a){cout<<"A (" << &a << "->" << this << ") Copy Construction"<<endl;}
~A() {cout<<"A (" << this << ") Destruction" <<endl;}
У меня есть вывод
A (0xbffff8cf) Construction
A (0xbffff8cf->0x100160) Copy Construction
A (0xbffff8cf) Destruction
A (0xbffff8ce) Construction
A (0x100160->0x100170) Copy Construction
A (0xbffff8ce->0x100171) Copy Construction
A (0x100160) Destruction
A (0xbffff8ce) Destruction
A (0x100170) Destruction
A (0x100171) Destruction
Таким образом, поток можно интерпретировать как:
- Временный A (... cf) создан.
- Временный A (… cf) копируется в вектор (… 60).
- Временный А (... ср) уничтожен.
- Еще один временный A (... ce) создан.
- Вектор расширяется, и старый A (… 60) в этом векторе копируется в новое место (… 70)
- Другой временный A (… ce) копируется в вектор (… 71).
- Все ненужные копии A (… 60,… ce) теперь уничтожены.
- Вектор уничтожен, поэтому внутри него также уничтожаются буквы A (… 70,… 71).
Шаг 5 пропадет, если вы выполните
vector<A> t;
t.reserve(2); // <-- reserve space for 2 items.
t.push_back(A());
t.push_back(A());
Вывод станет:
A (0xbffff8cf) Construction
A (0xbffff8cf->0x100160) Copy Construction
A (0xbffff8cf) Destruction
A (0xbffff8ce) Construction
A (0xbffff8ce->0x100161) Copy Construction
A (0xbffff8ce) Destruction
A (0x100160) Destruction
A (0x100161) Destruction