正确删除嵌套的类对象?

时间:2014-09-12 22:10:05

标签: c++

我的代码如下,基本上我正在使用一些外部库并将这个库中的一些类对象嵌入到myClass中,然后用OBJ做事,

#include  "extern_lib.h" //some library

class myClass
{
public:
extern_class *obj1;
extern_class *obj2;
double arr[3];
};

int main()
{

myClass *OBJ= new myClass();

OBJ->obj1 = new extern_class(arg1...);
OBJ->obj2 = new extern_class(arg2...);

//do something like

OBJ->obj1->extern_fun1(arg1...);
OBJ->obj2->extern_fun2(arg2...);

//delete 
delete OBJ;

return 0;
}

我想知道,

1-为了释放所有对象,是否足以删除OBJ?

2-是否有更好的方法来编写此代码?

2 个答案:

答案 0 :(得分:3)

  1. 不,这还不够。您必须为代码中明确放置的每个delete致电new
  2. 使用std::unique_ptr或更好的智能指针,使用RAII。为了澄清这一点:智能指针和RAII甚至不仅仅是更好的方式,它们是 在现代C ++中正确执行它的方式。
  3. 以下是 RAII

    的充分示例
    #include "extern_lib.h"
    
    class myClass
    {
    public: // note that public members are possibly bad design (depending on your situation)
        extern_class obj1;
        extern_class obj2;
        double arr[3];
    };
    
    int main()
    {
        myClass foo;
        foo.obj1.extern_fun(arg1...);
        foo.obj2.extern_fun(arg2...);
    
        return 0;
    }
    

    请注意,在任何情况下都无法使用RAII。如果遇到这种情况,请按照说明使用智能指针:

    #include "extern_lib.h"
    
    class myClass
    {
    public: // note that public members are possibly bad design (depending on your situation)
        std::unique_ptr<extern_class> obj1;
        std::unique_ptr<extern_class> obj2;
        double arr[3];
    };
    
    int main()
    {
        myClass foo;
        foo.obj1 = std::unique_ptr<extern_class>(new extern_class(arg1...));
        foo.obj2 = std::unique_ptr<extern_class>(new extern_class(arg2...));
    
        foo.obj1->extern_fun(arg1...);
        foo.obj2->extern_fun(arg2...);
    
        return 0;
    }
    

答案 1 :(得分:2)

  

为了释放所有对象,删除OBJ是否足够?

不会,这会产生资源泄漏,因为myClass的(默认)析构函数不关心删除指针成员。

  

有更好的方法来编写此代码吗?

是的,使用智能指针。例如:

class myClass
{
public:
  std::unique_ptr<extern_class> obj1;
  std::unique_ptr<extern_class> obj2;
  double arr[3];
};

通常,尝试按类创建资源拥有。也就是说,在构造函数中分配它们并在析构函数中释放它们。标准库的智能指针已经为您完成了这项工作。避免在单个类中管理多个资源。

顺便说一句:如果你的例子没有做作,而你根本就没有使用多态,那么只需要删除所有new并简单地使用具有自动存储持续时间的变量。 C ++不是Java。

更新:如果不需要多态性,这是(一种方法)如何摆脱new

class myClass
{
public:
  extern_class obj1;
  extern_class obj2;
  double arr[3];

  myClass(type arg1a, ..., type arg2a, ...) : obj1(arg1a, ...), obj2(arg2a, ...)
  //                                          ^^^^ member initializer list ^^^^
  {
  }
};

关键是通过使用所谓的成员初始化列表来创建成员对象,作为创建myClass的过程的一部分。如果您正在编写C ++ 11,则更喜欢编写obj1 {arg1a, ...}, obj2 {arg2a, ...}以保持一致性。 (然而,旧的语法仍然可以正常工作。)

同样在main函数中:

int
main()
{
  myClass mc(arg1a, ..., arg2a, ...);  // (1)
  mc.obj1.extern_func(...);
  mc.obj2.extern_func(...);
  return 0;  // (2)
}

在第(1)行,我们使用我们的新构造函数在堆栈上创建myClass的实例,该构造函数将正确创建成员obj1obj2myClass的编译器生成的默认构造函数将正确地破坏mc.obj1mc.obj2,因为mc超出了第(2)行的范围。同样,在C ++ 11中,第1行(1)可以更加干净地编写为myClass mc {arg1a, ..., arg2a, ...};