Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Destructor called on object when adding it to std::list

I have a Foo object, and a std::list holding instances of it. My problem is that when I add a new instance to the list, it first calls the ctor but then also the dtor. And then the dtor on another instance (according to the this pointer).

A single instance is added to the list but since its dtor (along with its parents) is called, the object cant be used as expected.

Heres some simplified code to illustrate the problem:

#include <iostream>
#include <list>

class Foo
{
public:
    Foo()
    { 
        int breakpoint = 0;
    }
    ~Foo()
    { 
        int breakpoint = 0;
    }
};

int main()
{
    std::list<Foo> li;
    li.push_back(Foo());
}
like image 226
Mizipzor Avatar asked Feb 05 '09 08:02

Mizipzor


People also ask

How do you call a destructor of an object in C++?

Use the obj. ~ClassName() Notation to Explicitly Call a Destructor Function. Destructors are special functions that get executed when an object goes out of scope automatically or is deleted by an explicit call by the user.

Does destructor get called automatically?

A destructor is a member function that is invoked automatically when the object goes out of scope or is explicitly destroyed by a call to delete . A destructor has the same name as the class, preceded by a tilde ( ~ ).

When should a destructor be called?

Destructors are usually used to deallocate memory and do other cleanup for a class object and its class members when the object is destroyed. A destructor is called for a class object when that object passes out of scope or is explicitly deleted.

How do you make sure a destructor is called?

the destructor is called when code is execused to line "finish". If the object is created via a pointer(for example,A * a2 = new A();),the destructor is called when the pointer is deleted(delete a2;).


2 Answers

When you push_back() your Foo object, the object is copied to the list's internal data structures, therefore the Dtor and the Ctor of another instance are called.

All standard STL container types in C++ take their items by value, therefore copying them as needed. For example, whenever a vector needs to grow, it is possible that all values in the vector get copied.

Maybe you want to store pointers instead of objects in the list. By doing that, only the pointers get copied instead of the object. But, by doing so, you have to make sure to delete the objects once you are done:

for (std::list<Foo*>::iterator it = list.begin(); it != list.end(); ++it) {
    delete *it;
}
list.clear();

Alternatively, you can try to use some kind of 'smart pointer' class, for example from the Boost libraries.

like image 83
Ferdinand Beyer Avatar answered Oct 29 '22 19:10

Ferdinand Beyer


You are creating a temporary Foo here:

li.push_back( Foo() )

push_back copies that Foo into its internal data structures. The temporary Foo is destroyed after push_back has been executed, which will call the destructor.

You will need a proper copy constructor that increases some reference count on the class members that you do not want to destroy early -- or make it private to force yourself on the pointer solution.

like image 26
Timbo Avatar answered Oct 29 '22 19:10

Timbo