Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

std::vector calling destructor multiple times during push_back?

Tags:

c++

c++11

vector

I'm pushing objects class tipo to a vector, when I push the first one the constructor get's called (as it should) and the destructor is called immediatelly (which I don't think should happen). Then when I push the next object the constructor is called once and the destructor is called twice, then on the third three times and so on.

It seems that the destructor is called more times every time I push something to the vector.

This is my class:

class Item
{
protected:
...
public:
    Item();
    Item(char * no, int hit, int ve, char * pathTilesheet, int an, int al, bool inv, bool vol, bool fan, int mh = NULL);
    ~Item();
};


Item::Item(char *no, int hi, int ve, char *pathTilesheet, int an, int al, bool inv, bool vol, bool fan, int mh){    
    // CARGAR SDL
    tileSheet = load_image(pathTilesheet);
    tileSheetEspejo = flip_surface(tileSheet, FLIP_HORIZONTAL);
}

This is what is happening:

std::vector<Item> vecItems;
vecItems.push_back(Item("life",4,0,"assets/imagenes/hp.png", 8, 8, false, false, false));
// HERE THE CONSTRUCTOR AND THE DESTRUCTOR ARE CALLED
vecItems.push_back(Item("lifeXL",8,0,"assets/imagenes/hp-xl.png", 16, 16, false, false, false));
// HERE THE CONSTRUCTOR IS CALLED ONCE AND THE DESTRUCTOR TWICE
vecItems.push_back(Item("blast 1",-4,14,"assets/imagenes/bola.png", 8, 8, false, true, false));
// HERE THE CONSTRUCTOR IS CALLED ONCE AND THE DESTRUCTOR MULTIPLE TIMES

Am I doing something wrong? Why could this be happening?

like image 376
lisovaccaro Avatar asked Dec 08 '22 11:12

lisovaccaro


1 Answers

Each line of your code creates a temporary Item, copies it into the vector's memory, and then destroys the temporary. That's why you see (at least) one destructor call each time.

In C++11, you could avoid creating and destroying the temporary by using emplace_back(args...) rather than push_back(Item(args...)), to create the object directly in the vector's memory.

Additionally, the vector sometimes needs to grow, reallocating a larger block of memory, in order to keep all its elements in a contiguous array. When it does that, each element is moved into the new memory, and the old elements are destroyed. That's why you sometimes see more than one destructor call.

You can avoid the need for reallocation, if you know the final size of the vector, by calling reserve() to allocate enough memory before you start. Alternatively, there are containers like deque and list which don't move their elements as they grow, but which may be less efficient for other operations.

As an aside, as noted in the comments, if the class is managing resources (which is implied by the presence of a destructor), you probably need to provide or delete the copy constructor and copy-assignment operator per the Rule of Three, and perhaps think about making it movable for efficiency.

like image 146
Mike Seymour Avatar answered Dec 11 '22 11:12

Mike Seymour