为什么这个物体不被摧毁?

时间:2022-12-29 15:50:15

I have spending ages trying to figure out why this is happening.

我花了很长时间试图弄明白为什么会这样。

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

I get:

我得到:

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

The destructor for Element 1 never gets called? At first I didn't know why Element number 4 destructor would get called when erasing the first element, and then I thought when it shifts its members maybe the destructor has to get called. But the documentation says that all of the members after the one deleted get shifted, and the destructors of 2 and 3 didn't get called. I am really confused.

元素1的析构函数没有被调用?一开始我不知道当删除第一个元素时为什么会调用第4个析构函数,然后我想当它移动它的成员时可能会调用析构函数。但是文件上说,删除一个之后的所有成员都被转移了,2和3的析构函数没有被调用。我真的很困惑。

EDIT: Well if this is an optimisation step, then the documentation is wrong, because:

编辑:如果这是优化步骤,那么文档是错误的,因为:

Removes from the vector either a single element (position) or a range of elements ([first,last)).

从向量中移除单个元素(位置)或一系列元素([第一个,最后一个)]。

This effectively reduces the container size by the number of elements removed, which are destroyed.

这有效地减少了容器的大小,减少了被破坏的元素的数量。

That's not destroying then.

这不是破坏。

1 个解决方案

#1


14  

vector is trying to save performance.

vector试图保存性能。

What erase does is it copies elements 2, 3 and 4 down one element, overwriting the element containing 1. So the first element now contains 2, etc. Then it destroys the last element, which is a copy of 4.

擦除的作用是将元素2 3 4向下复制一个元素,覆盖包含1的元素。第一个元素现在包含2,然后它会破坏最后一个元素,也就是4的拷贝。

That has the effect of erasing the first element, but not quite in the way you thought it would. It erases the contents of the first element, but not the object itself.

这有消除第一个元素的效果,但不是你想象的那样。它删除第一个元素的内容,而不是对象本身。

Depending on the type you store in your vector, this will be less expensive than destroying the first element, only to reconstruct a copy of the second element in the storage of the first.

根据您在向量中存储的类型,这将比破坏第一个元素要便宜,只需要在第一个元素的存储中重构第二个元素的副本。

Well if this is an optimisation step, then the documentation is wrong, because:

如果这是一个优化步骤,那么文档是错误的,因为:

...

That's not destroying then.

这不是破坏。

The documentation is correct, and it is destroying them.

文件是正确的,它正在破坏它们。

Your objects are the values they contain. You declared that your classes were copyable, so vector is free to copy them. That means it's perfectly legitimate for two instances to have the same value. vector exploits that.

对象是它们所包含的值。您声明了您的类是可复制的,所以vector可以*地复制它们。这意味着两个实例具有相同的值是完全合法的。利用向量。

If you had made your classes non-copyable but noexcept moveable, then it would work correctly. But your move constructor would also need to null-out the moved-from object, so that no two instances would have the same value.

如果您已经使您的类不可复制但不可移动,那么它将正确地工作。但是,您的move构造函数还需要将moved-from对象空出来,以便没有两个实例具有相同的值。

#1


14  

vector is trying to save performance.

vector试图保存性能。

What erase does is it copies elements 2, 3 and 4 down one element, overwriting the element containing 1. So the first element now contains 2, etc. Then it destroys the last element, which is a copy of 4.

擦除的作用是将元素2 3 4向下复制一个元素,覆盖包含1的元素。第一个元素现在包含2,然后它会破坏最后一个元素,也就是4的拷贝。

That has the effect of erasing the first element, but not quite in the way you thought it would. It erases the contents of the first element, but not the object itself.

这有消除第一个元素的效果,但不是你想象的那样。它删除第一个元素的内容,而不是对象本身。

Depending on the type you store in your vector, this will be less expensive than destroying the first element, only to reconstruct a copy of the second element in the storage of the first.

根据您在向量中存储的类型,这将比破坏第一个元素要便宜,只需要在第一个元素的存储中重构第二个元素的副本。

Well if this is an optimisation step, then the documentation is wrong, because:

如果这是一个优化步骤,那么文档是错误的,因为:

...

That's not destroying then.

这不是破坏。

The documentation is correct, and it is destroying them.

文件是正确的,它正在破坏它们。

Your objects are the values they contain. You declared that your classes were copyable, so vector is free to copy them. That means it's perfectly legitimate for two instances to have the same value. vector exploits that.

对象是它们所包含的值。您声明了您的类是可复制的,所以vector可以*地复制它们。这意味着两个实例具有相同的值是完全合法的。利用向量。

If you had made your classes non-copyable but noexcept moveable, then it would work correctly. But your move constructor would also need to null-out the moved-from object, so that no two instances would have the same value.

如果您已经使您的类不可复制但不可移动,那么它将正确地工作。但是,您的move构造函数还需要将moved-from对象空出来,以便没有两个实例具有相同的值。