std :: vector在push_back期间多次调用析构函数?

时间:2013-11-10 15:30:57

标签: c++ c++11 vector

我正在将对象类tipo推送到向量,当我按下第一个被调用的构造函数时(因为它应该)并且析构函数被称为immediatelly(我认为不应该发生)。然后当我按下下一个对象时,构造函数被调用一次,析构函数被调用两次,然后是第三次被调用,依此类推。

每次我向向量推送东西时,似乎都会多次调用析构函数。

这是我的班级:

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);
}

这就是发生的事情:

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

我做错了吗?为什么会发生这种情况?

1 个答案:

答案 0 :(得分:13)

代码的每一行都会创建一个临时Item,将其复制到向量的内存中,然后销毁临时代码。这就是你每次都看到(至少)一个析构函数调用的原因。

在C ++ 11中,您可以使用emplace_back(args...)而不是push_back(Item(args...))来避免创建和销毁临时文件,直接在向量的内存中创建对象。

此外,向量有时需要增长,重新分配更大的内存块,以便将其所有元素保持在连续的数组中。当它这样做时,每个元素都被移动到新的内存中,旧的元素被破坏。这就是为什么你有时会看到多个析构函数调用。

如果您知道向量的最终大小,则可以通过在开始之前调用reserve()来分配足够的内存来避免重新分配的需要。或者,有dequelist这样的容器,它们不会随着它们的增长而移动它们的元素,但对于其他操作来说可能效率较低。

另外,如评论中所述,如果类是管理资源(由析构函数的存在暗示),您可能需要提供或删除复制构造函数和复制赋值运算符Rule of Three,也许考虑让它可以提高效率。