Почему деструктор класса вызывается дважды? - PullRequest
21 голосов
/ 13 апреля 2010

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

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

Ответы [ 5 ]

42 голосов
/ 13 апреля 2010

Чтобы добавить элемент, вызывается конструктор копирования для временного объекта. После push_back() временный объект уничтожается - это не первый вызов деструктора. Затем экземпляр vector выходит из области видимости и уничтожает все сохраненные элементы - это второй вызов деструктора.

25 голосов
/ 13 апреля 2010

Это покажет вам, что происходит :

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());
}
4 голосов
/ 13 апреля 2010

Деструктор вызывается один раз, когда временная отправка на push_back уничтожается, и один раз, когда уничтожается элемент в t.

2 голосов
/ 09 января 2016

Есть два вызова деструктора, потому что есть два объекта: аргумент push_back и недавно добавленный элемент в vector t.

Контейнеры STL Храните копии. В вашем примере элемент, добавленный к vector с помощью push_back, является копией, созданной из аргумента, переданного push_back. Аргументом является A(), который является временным объектом, см. здесь (вариант 4) .

Немного расширив ответ, хотя вы явно не спросили его: может быть полезно знать, когда временный уничтожен. Стандарт ( N4140 ) говорит о нем довольно ясно в 12.2 p3:

... Временные объекты уничтожаются как последний шаг в оценке полное выражение (1.9), которое (лексически) содержит точку, где они были созданы ...

Примечание: если вы используете emplace_back, есть только один объект. Новый элемент в контейнере напрямую создается из аргументов emplace_back. Многие STL-контейнеры изучили вариант emplace в C ++ 11.

0 голосов
/ 09 января 2016

Скорее всего, копия вашего объекта создается. Из-за этого деструктор для скопированного объекта и для исходного объекта делает 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;
}
...

Подробнее @ stackoverflow @

...