4

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?

lisovaccaro
  • 32,502
  • 98
  • 258
  • 410

1 Answers1

15

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.

Community
  • 1
  • 1
Mike Seymour
  • 249,747
  • 28
  • 448
  • 644
  • @Yakk: That's not directly relevant to the question; but yes, if the class needs a destructor then it probably needs its copy semantics fixing or disabling. – Mike Seymour Nov 10 '13 at 15:42
  • His question is why the destructor is called more often than the constructor. That is because he missed implementing the copy constructor and assignment operator. As you can see, the OP allocates resources in the ctor, which are probably cleaned up in the dtor, which causes problems when thr dtor is called 3 times for one ctor. The OP has asked the wrong question, and the right answer involves writing a copy ctor. – Yakk - Adam Nevraumont Nov 10 '13 at 16:17
  • @Yakk: The question asks why the destructor is called multiple times, and my answer explains why. I've added a note as to why that's a problem if the class has invalid copy semantics, even though that's only marginally relevant. – Mike Seymour Nov 10 '13 at 16:26