【问题标题】:Delete vector class member删除向量类成员
【发布时间】:2014-02-03 18:04:15
【问题描述】:

我有一个类 A,它的成员是另一个类 B 的对象指针向量

class A
{
    std::vector<B*> m_member_A

m_member_A 是通过使用 new 运算符创建 B 的对象来填充的

B* b1 = new B;
m_member_A.push_back(b1);

在 A 的析构函数中,释放所有内容是否正确?

A::~A()
{
    for(int i = 0; i < m_member_A.size(); ++i)
    {
        delete m_member_A[i];
    }

    m_member_A.clear();
}

【问题讨论】:

  • 是的,这是正确的方法,实际上是 c++11 之前的唯一方法。在c ++ 11中,您可以只使用vector>,它会自动释放
  • '在 A 的析构函数中,下面的释放一切是否正确?' 是的,它是正确的。您为什么不使用像valgrind 这样的良好内存泄漏检测工具自己检查一下?
  • 看起来不错。你有什么理由认为它不正确吗?

标签: c++ class vector destructor member


【解决方案1】:

这是正确的,只要您还根据Rule of Three 有一个正确的复制构造函数和复制赋值运算符。注意clear() 是多余的,因为向量的析构函数会释放它的内存。

你为什么要搞乱指针和new?如果您需要多态性指针,为什么不遵循零规则并使用vector&lt;B&gt;vector&lt;unique_ptr&lt;B&gt;&gt;?那么你根本不需要担心析构函数、复制构造函数或复制赋值运算符;并且您将获得移动语义作为奖励。

【讨论】:

  • @Mike Seymour 为了安全起见,我应该在delete m_member_A[i] 之前检查空指针吗?
  • @ontherocks:不,给delete一个空指针是安全的;它不会对它做任何事情。
  • @Mike Seymour。谢谢。如果m_member_Astd::map&lt;int, string&gt;,并且这是A 的唯一成员,我是否需要像A::~A(){ m_member_A.clear(); } 那样实现A 的析构函数,或者这也是多余的?如果它是多余的,那么我想默认的析构函数就足够了。
  • @ontherocks:确实,这是多余的。销毁设计合理的类时,您永远不需要做任何事情;这就是使用析构函数的全部意义所在。
【解决方案2】:

是的,没错……但这还不够。

您还需要在复制 A 时对容器进行深度复制。

如果您可以在向量内使用智能指针,那就更好了。只要在你的头脑和你的代码中清楚谁拥有什么。

【讨论】:

    【解决方案3】:

    差不多

    如果您在 A 的构造函数中构造(分配)B 的元素并且某些 B 抛出异常,则您有内存泄漏(除非它在删除 B 的 A 的构造函数中被捕获)

    还有通常的三法则。

    一些说明可能是(请将 MAKE_FAILURE 调整为 0 或 1):

    #include <iostream>
    #include <stdexcept>
    #include <vector>
    
    #define MAKE_FAILURE 0
    
    static unsigned count;
    const unsigned ExceptionThreshold = 3;
    struct B {
        B() { if(ExceptionThreshold <= count++) throw std::runtime_error("Sorry"); }
        ~B() { std::cout << "Destruct\n"; }
    };
    
    struct A
    {
        std::vector<B*> v;
        A()
        {
            for(unsigned i = 0; i < ExceptionThreshold + MAKE_FAILURE; ++i)
                v.push_back(new B);
        }
    
        ~A()
        {
            for(unsigned i = 0; i < v.size(); ++i) {
                delete v[i];
            }
        }
    };
    
    int main()
    {
        A a;
        return 0;
    }
    

    你也进入了浅拷贝和深拷贝的领域(正如@提到的那样 Orb 中的轻量级竞赛)

    【讨论】:

      【解决方案4】:

      这是释放 m_member_A 向量中动态分配对象内存的正确方法。你实际上不需要打电话:

      m_member_A.clear();
      

      std::vector 会自行释放内存。

      如果你可以使用C++11,那我建议改成shared_ptr:

        std::vector<std::shared_ptr<B>> m_member_A
      

      现在你不需要自己释放内存了。

      【讨论】:

        猜你喜欢
        • 2018-01-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-06-19
        • 1970-01-01
        • 2013-12-30
        • 1970-01-01
        相关资源
        最近更新 更多