34

Apologies if the question sounds silly, I was following experts in SO and trying some examples myself, and this is one of them. I did try the search option but didn't find an answer for this kind.

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.
}

Why is the destructor of the class called twice ?

knittl
  • 246,190
  • 53
  • 318
  • 364
dicaprio
  • 713
  • 2
  • 8
  • 25
  • Don't think SO supports the `` tag. Though, maybe a feature request on meta? Methinks Jeff's gonna love it! :-) – Franci Penov Apr 13 '10 at 06:54
  • @pst: Thank you, I was doing the edit and before I could save it was done. – dicaprio Apr 13 '10 at 06:57
  • 6
    Just wondering, why is this community wiki? – jasonline Apr 13 '10 at 07:09
  • @dicaprio: a follow up [ http://stackoverflow.com/questions/2657752/extraneous-calls-to-copy-constructor-and-destructor ] – Lazer Apr 17 '10 at 08:29
  • With `t.emplace_back()` instead (C++0x), only one A object, and only one destructor call. – rafak May 05 '10 at 13:50
  • Just in case anyone arrived here after finding their destructor being called twice was leading to attempts to relinquish resources being made twice —to resolve your issue you probably have to provide a _move constructor_ for your class with resources being freed in the destructor, so you can basically "nullify" the donor object for the copy. This solved my issue: https://learn.microsoft.com/en-us/cpp/cpp/move-constructors-and-move-assignment-operators-cpp?view=msvc-170 – saxbophone Feb 08 '23 at 20:12

5 Answers5

50

To add the element a copy constructor is invoked on a temporary object. After the push_back() the temporary object is destroyed - that't the first destructor call. Then vector instance goes out of scope and destroys all the elements stored - that's the second destructor call.

sharptooth
  • 167,383
  • 100
  • 513
  • 979
  • @sharptooth& @Andreas: Thank you. I just tried after seeing your reply, I defined a copy constructor A(ConstA&) and yes it get called. – dicaprio Apr 13 '10 at 07:16
  • 4
    @dicaprio: Sure, until you defined your own copy constructor the compiler used its own automatically generated copy constructor. – sharptooth Apr 13 '10 at 07:42
27

This will show you what's happening:

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());
}
  • !Roger : I tried the same just before you posted this, I got the point, thank you !! – dicaprio Apr 13 '10 at 07:17
  • how can we allow copy constructor copy correctly and use `cout` and not calling itself and initiating constructor? is the only to assign fields one by one? – ar2015 May 24 '20 at 00:12
4

The destructor is called once when the temporary sent to push_back is destroyed and once when the element in t is destroyed.

Andreas Brinck
  • 51,293
  • 14
  • 84
  • 114
3

There are two destructor calls because there are two objects: the argument to push_back, and the newly added element within vector t.

STL containers store copies. In your example the element added to the vector by push_back is copy constructed from the argument passed to push_back. The argument is A(), which is a temporary object, see here (variant 4).

Expanding the answer a bit, altough you havent explicitely asked for it: It might be useful to know when the temporary is destroyed. The standard (N4140) sais it pretty clearly in 12.2 p3:

... Temporary objects are destroyed as the last step in evaluating the full-expression (1.9) that (lexically) contains the point where they were created...

Side note: If you use emplace_back there is only one object. The new element in the container is directly constructed from the arguments to emplace_back. Many STL container learned an emplace variant in C++11.

Community
  • 1
  • 1
Florian Kaufmann
  • 803
  • 6
  • 13
0

Most probably, copy of your object is getting created. Because of which, the destructor for the copied-object, and for the original-object makes the call-count=2.

Example: Even though, you are passing the object reference, to some class, this internally would invoke the copy-constructor. To avoid this, the child-class (to which you are passing the parent reference, must be as;

Parent *const &p parentRef;  //Child.h

Then, the parent object will be passed as;

// Parent.cpp
Parent *parentObj = this;
Child *childObj = Child(parentObj);

Additionally, you can debug the copy-constructor invokation, by overriding;

Parent(const Parent& object){
        cout <<"copy called.." << endl;
}
...

More info @stackoverflow@

Community
  • 1
  • 1
parasrish
  • 3,864
  • 26
  • 32