31

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
  • 216,605
  • 51
  • 293
  • 340
dicaprio
  • 693
  • 2
  • 8
  • 25

5 Answers5

49

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
  • 163,328
  • 92
  • 501
  • 942
  • @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
  • 49,374
  • 14
  • 81
  • 112
2

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,466
  • 24
  • 29