无论如何重新分配时,std::vector 调用都包含对象的析构函数?

Zeb*_*ish 2 c++ resources destructor release vector

每当我的对象的向量被重新分配时,对象的析构函数就会被调用,这给我带来了问题。

struct Object
    {
        Object(int buffer_ID) : buffer_ID(buffer_ID){ OpenGLCreateBuffer(buffer_ID, somedata);}
        ~Object() { OpenGLDeleteBuffer(buffer_ID); }
        int buffer_ID;
    };

    int main()
    {
        std::vector<Object> objArr;
        objArr.push_back(1);
        objArr.push_back(2);             // Destructor is called when reallocating vector

        OpenGLDrawBuffer(objArr[0].buffer_ID);       // The buffer has been deleted

    }
Run Code Online (Sandbox Code Playgroud)

这真的很烦人,我不明白为什么要在正在移动的对象上调用析构函数。我环顾四周,我很满意你不能阻止析构函数被调用。使用移动语义,我认为使用的技巧是从另一个对象复制内容,并将任何指针设置为 null,这样当对它们调用析构函数并释放资源时,delete 只是在 nullptr 上调用。

我首先尝试创建一个复制构造函数,并尝试将另一个 buffer_ID 设置为 0,但这仅在复制构造函数采用非常量引用时才有效,这似乎不正确。此外,将其他变量设置为 null 以便随后在 null 上调用 delete 的行为,或者将 null 传递给像在这种情况下的 OpenGL 删除函数之类的东西,看起来很糟糕,不是吗?

我知道我会被告知我无法阻止调用析构函数,那么如果对象可能被重新分配到另一部分,我该怎么办?我认为析构函数是删除此类内容的最佳位置。

谢谢。

Sam*_*hik 6

你的班级似乎违反了三原则。它的析构函数似乎破坏了不是在其构造函数中创建的资源。

你真正的问题是你的类的基本设计与std::vector工作方式不兼容。当向量必须重新分配其内容时,它将复制构造或移动构造(如果向量的类支持移动语义)现有实例,然后销毁所有旧类实例。这就是向量的工作方式。这就是它的设计方式。如果您的类不能那样工作,则不能使用std::vector. 使用std::list可能是一种选择。

但更好的选择是修复您的课程。重新设计,使其符合三规则。这样做之后,进一步扩展您的类以添加移动构造函数,并适当支持移动语义。