我花了很多年时间试图弄清楚为什么会这样。
struct Element
{
Element(int number) : number_ID(number)
{ std::cout << "Element number " << number_ID << " is being constructed\n"; }
~Element()
{ std::cout << "Element number " << number_ID << " is being destroyed\n"; }
int number_ID;
};
void createVector()
{
std::vector<Element> objArr;
objArr.reserve(10); // So it doesn't have to reallocate
objArr.emplace_back(1);
objArr.emplace_back(2);
objArr.emplace_back(3);
objArr.emplace_back(4);
objArr.erase(objArr.begin()); // When I erase the first element only element 4 has destructor called
}
int main()
{
createVector();
system("pause");
}
我明白了:
Element number 1 is being constructed
Element number 2 is being constructed
Element number 3 is being constructed
Element number 4 is being constructed
//The following called when doing objArr.erase(objArr.begin());
Element number 4 is being destroyed
//The following called after createVector() function exits
Element number 2 is being destroyed
Element number 3 is being destroyed
Element number 4 is being destroyed
元素1的析构函数永远不会被调用?起初我不知道为什么在擦除第一个元素时会调用元素4的析构函数,然后我想当它移动它的成员时可能必须调用析构函数。但文档说,删除一个成员之后的所有成员都会被移位,并且2和3的析构函数没有被调用。我真的很困惑。
编辑:如果这是一个优化步骤,那么文档是错误的,因为:
从向量中移除单个元素(位置)或范围 元素([first,last))。
这有效地减少了容器大小的元素数量 被删除,被摧毁。
那不是在破坏。
答案 0 :(得分:14)
vector
正试图保存效果。
erase
做的是将元素2,3和4复制到一个元素下面,覆盖包含1的元素。所以第一个元素现在包含2,等等。然后它会破坏最后一个元素,这是一个副本4。
它具有擦除第一个元素的效果,但并不像你想象的那样。它会删除第一个元素的内容,但不会删除对象本身。
根据您在vector
中存储的类型,这将比销毁第一个元素更便宜,只是为了重建第一个元素存储中的第二个元素的副本。
如果这是一个优化步骤,那么文档是错误的,因为:
...
那不是在破坏。
文档是正确的,它正在摧毁它们。
您的对象是它们包含的值。您声明您的类是可复制的,因此vector
可以自由复制它们。这意味着两个实例具有相同的值是完全合法的。 vector
利用了这一点。
如果你使你的课程不可复制但是不可移动,那么它将正常工作。但是你的移动构造函数也需要将移动的对象置零,这样就不会有两个实例具有相同的值。