【问题标题】:std::vector calls contained object's destructor when reallocating no matter what?std::vector 在重新分配时调用包含对象的析构函数,无论如何?
【发布时间】:2017-06-11 09:33:02
【问题描述】:

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

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

    }

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

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

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

谢谢。

【问题讨论】:

  • 让你的对象遵守“三法则”(或 C++11 中的“五法则”)。
  • 最好有一个对象指针向量 std::vector objArr;向量可以随心所欲地增长\收缩,但指针仍然有效。

标签: c++ vector resources destructor release


【解决方案1】:

你的班级出现在violate the Rule Of Three。它的析构函数似乎要销毁不是在其构造函数中创建的资源。

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

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

【讨论】:

  • 在析构函数中删除的buffer_ID是在构造函数中创建的,我只是没有显示出来,对不起,我在插图中遗漏了那一点。你是对的,矢量可能不适合我。如果我要创建自己的向量类,它可能不会在移动时调用析构函数。
  • 如果是这样,那么您的向量将不是 C++。对于 C++ 来说,每个类实例的创建都必须导致构造函数调用,并且每个类实例的销毁都必须导致析构函数调用。没有例外。 C++11 引入的移动语义正是您要寻找的。之所以引入它们,正是为了实现一种有效的移动对象方式,同时仍保持 C++ 使用对象的基本方式不变。
【解决方案2】:

您可以使用 mutable 来解决复制构造函数中的 const 问题。 为什么不在传入的类中添加一个释放方法来将指针归零。

【讨论】:

  • 在原始帖子中“但这仅在复制构造函数采用非常量引用时才有效”。也重新。编码 OP 在他们的帖子中提到删除指针。
  • 是的,对不起,我重新阅读了这个问题,看到你来自哪里。我仍然认为这不能回答这个问题。 mutable(或const_cast)不是正确的解决方案。移动构造函数和正确的所有权语义是。
  • 再次阅读我之前的评论。 OP 不需要mutable 或任何类型的发布方法。 OP 需要一个移动构造函数。
猜你喜欢
  • 2018-10-25
  • 1970-01-01
  • 1970-01-01
  • 2022-06-10
  • 2012-03-15
  • 1970-01-01
  • 2020-08-14
  • 2011-02-14
  • 2020-06-05
相关资源
最近更新 更多