Почему деструктор класса называется дважды?
Извиняется, если вопрос звучит глупо, я следил за экспертами в SO и сам пробовал некоторые примеры, и это один из них. Я попробовал вариант поиска, но не нашел ответа для такого рода.
class A
{
public:
A(){cout<<"A Contruction"<<endl;}
~A(){cout<<"A destruction"<<endl;}
};
int main()
{
vector<A> t;
t.push_back(A()); // After this line, when the scope of the object is lost.
}
Почему деструктор класса дважды называется?
Ответы
Ответ 1
Чтобы добавить элемент, конструктор копирования вызывается во временном объекте. После push_back()
временный объект уничтожается - это первый вызов деструктора. Затем экземпляр vector
выходит за пределы области видимости и уничтожает все сохраненные элементы - второй вызов деструктора.
Ответ 2
Это покажет вам, что происходит:
struct A {
A() { cout << "contruction\n"; }
A(A const& other) { cout << "copy construction\n"; }
~A() { cout << "destruction\n"; }
};
int main() {
vector<A> t;
t.push_back(A());
}
Ответ 3
Деструктор вызывается один раз, когда временное отправление на push_back
уничтожается и один раз, когда элемент в t
уничтожается.
Ответ 4
Существует два вызова деструктора, потому что есть два объекта: аргумент push_back
и вновь добавленный элемент внутри vector
t
.
Контейнеры STL хранят копии. В вашем примере элемент, добавленный в vector
от push_back
, является копией, построенной из аргумента, переданного в push_back
. Аргумент A()
, который является временным объектом, см. здесь (вариант 4).
Немного измените ответ, хотя вы его явно не задали: может быть полезно знать, когда временное уничтожено. Стандарт (N4140), это довольно ясно в 12.2 p3:
... Временные объекты уничтожаются как последний шаг при оценке полное выражение (1.9), которое (лексически) содержит точку, в которой они были созданы...
Примечание: если вы используете emplace_back
, существует только один объект. Новый элемент в контейнере напрямую создается из аргументов в emplace_back. Многие контейнеры STL изучили вариант emplace в С++ 11.
Ответ 5
Скорее всего, создается копия вашего объекта. Из-за чего деструктор для скопированного объекта и для исходного объекта делает call-count = 2.
Пример. Несмотря на то, что вы передаете ссылку на объект, в какой-то класс, это внутренне вызовет экземпляр-конструктор. Чтобы этого избежать, дочерний класс (которому вы передаете родительскую ссылку, должен быть как:
Parent *const &p parentRef; //Child.h
Затем родительский объект будет передан как:
// Parent.cpp
Parent *parentObj = this;
Child *childObj = Child(parentObj);
Кроме того, вы можете отлаживать вызов-конструктор-экземпляр путем переопределения;
Parent(const Parent& object){
cout <<"copy called.." << endl;
}
...
Дополнительная информация fooobar.com/info/299265/...