Подтвердить что ты не робот

Почему деструктор класса называется дважды?

Извиняется, если вопрос звучит глупо, я следил за экспертами в 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.
}

Почему деструктор класса дважды называется?

4b9b3361

Ответ 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/...