在删除结构之前是否必须删除结构中的指针变量?

时间:2018-08-27 05:26:17

标签: c++ pointers

我已经开始使用C ++,并且需要一些有关C ++中的内存管理的说明。我遇到过智能指针,但是我希望了解一些基本概念。

这是一个示例结构

struct A
{
    private:
    int a;
    void* b;
    public:
    A(int i, void* m) { a=i; b=m; }
};

main()
{
    A * a1 = new A(10, 0);
    // 
    //Some Code
    if(on some condition) {
         delete a1;
         a1=nullptr;
    }
}

当我删除a1时,m是否也会被自动删除?还是应该在删除a1之前明确删除m,如下所示?

delete a1->b;
a1->b = nullptr;
delete a1;
a1=nullptr;

2 个答案:

答案 0 :(得分:4)

  

当我删除a1时,m也会自动删除

不,不会(您的代码可能有内存泄漏)。您需要一个明确的destructor删除它。

顺便说一句,使用void*b;指针字段的味道不好。如果您知道,则应该使用一些更明确的类型(例如double*b;SomeClass* b;)。这使您的代码更具可读性,并在编译时提供了更多有用的类型检查机会。

// inside struct A
~A() { delete b; };

了解rule of five

请注意,在C ++中,struct-s是very similarclass-es。

避免使用memory leaks。诸如valgrind之类的工具可能会有所帮助。并且系统地使用smart pointers和标准容器应该有助于避免它们。如果您的字段b was声明了std::shared_ptr<std::string> b;,则默认析构函数将适当地释放它。也许您希望它是某个std::vector<std::string>(同样,默认析构函数会适当地释放内存)。

一个好的编码提示是,在可能的情况下,避免声明raw pointers(最好使用智能指针和容器)。当必须声明一个时,您需要对其delete进行适当的编码。

答案 1 :(得分:2)

欢迎使用C ++,这是一种功能非常强大的语言,要求您对细节负责,以实现允许这种功能的灵活性。如果愿意,可以使其非常复杂,但是对于大多数结构而言,它们也是一种简便的方法。

首先,您不需要释放内存,如果程序退出,它将清除它。但是,由于您不调用delete,因此不会调用Dtor,这可能导致特定代码无法执行。 因此,通常,清理分配的内存是个好习惯。

如果不需要堆,请不要使用

new A(10, 0)将在堆上分配内存。如果您不希望这样做,也可以在堆栈上创建它。会导致自动清除:A a{10, nullptr};

使用RAII

一旦您决定需要堆分配的内存,则应默认为std::unique_ptr。它将代码更改为:auto a = std::make_unique<A>(10, nullptr);这样,所有权就在unique_ptr中,可以在(std :: move)中移动。如果您不想转让所有权,则可以取消引用它或调用方法get

应用这两种做法(包括针对成员的做法)将防止大量内存泄漏,并减少您需要考虑的时间。

请勿使用void *

void *是邪恶的,除非有必要,否则不要使用它(并且只有在与C接口时才必须使用)。有很多避免它的方法。最好的是引入一个界面。

class I {
public:
    virtual ~I() = default;
};

class M : public I
{
    // ...
};

class A
 {
      // ...
      std::unique_ptr<I> m;
      // ...
  };

需要一些特别的东西吗?

有时候,您在Dtor中需要一些特殊的东西,只有在这种情况下,您才应该明确实现Dtor。鉴于您的问题,我将假设您是一个初学者,因此暂时不需要了解更多详细信息。