【问题标题】:Does the synthesized destructor destroy the memory allocated on the heap?合成的析构函数会破坏堆上分配的内存吗?
【发布时间】:2021-12-31 18:20:50
【问题描述】:

我有一个没有析构函数和构造函数的类:

class Foo {
public:
    Foo(int a) : p(new int(a)) {}

private:
    int *p;
};
{
    Foo a(4);
}

在这段代码之后,堆上分配的内存会被释放吗? 还是我必须显式提供这样的析构函数:

class Foo {
public:
    Foo(int a) : p(new int(a)) {}
    ~Foo();

private:
    int *p;
};

Foo::~Foo() {
    delete p;
}

【问题讨论】:

    标签: c++ heap-memory destructor dynamic-memory-allocation


    【解决方案1】:

    我们使用new在堆上分配的任何内存必须始终使用关键字delete释放。

    因此,您必须像在析构函数中所做的那样,使用关键字delete 在堆上显式释放new 分配的内存。合成的析构函数不会为你做这件事。

    注意,如果您不想自己处理内存管理,那么您可以使用智能指针。这样您就不必自己显式使用delete,因为与智能指针对应的析构函数将负责释放内存。这实质上意味着如果名为 p 的数据成员是智能指针而不是普通(内置)指针,那么您 不必 在类的析构函数中写入 delete p @ 987654328@.

    【讨论】:

    • 这里的“必须”这个词有点太强了。如果您使用像std::unique_ptr<int> 这样的智能指针而不是int *,则该指针将被合成析构函数自动删除。
    • 但是当类更改为使用std::shared_ptr<int> p; 时,编译器生成的析构函数将释放内存。并且编译器生成的复制构造函数和赋值运算符将正常工作。 +1。
    【解决方案2】:

    作为对 Anoop 正确答案的补充:

    只需尝试“强调”编译器和运行时。如果发生析构函数调用,环境应该如何决定是否在指针上调用delete?它没有机会确定这一点,而且它实际上不是语言设计的工作(部分与 C# 和 Java 哲学相反)。指针也可以是非拥有的,其引用的动态分配的存储应该在您的特定析构函数调用中继续存在,甚至在您的类是分配器的情况下也是可能的(通常设计不好,但允许)。

    析构函数上下文只是“看到”成员,在这种情况下,这只是一个先验指针,而不是可能进一步动态分配的资源。 请尝试熟悉重要的RAII -技术,它不仅与动态内存分配有关。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-06-22
      • 1970-01-01
      • 2011-04-21
      • 1970-01-01
      • 2016-06-17
      • 1970-01-01
      • 1970-01-01
      • 2020-07-18
      相关资源
      最近更新 更多