我有一个没有析构函数和构造函数的类,如下所示:
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;
}
我们使用new
在堆上分配的任何内存都必须始终使用关键字delete
来释放。
因此,必须像在析构函数中那样,使用关键字delete
显式地释放堆上new
分配的内存。合成的析构函数不会为你做这件事。
请注意,如果您不想自己处理内存管理,则可以使用智能指针。这样,您就不必自己显式地使用delete
,因为与智能指针对应的析构函数将负责释放内存。这本质上意味着,如果名为p
的数据成员是智能指针,而不是普通(内置(指针,则不必在类Foo
的析构函数中写入delete p
。
作为Anoop正确答案的附加答案:
试着";强调";使用编译器和运行时。如果发生析构函数调用,环境应该如何决定是否在指针上调用delete
?它没有机会确定这一点,而且它实际上不是语言设计的工作(与C#和Java哲学形成部分对比(。指针也可以是一个非拥有者,其引用的动态分配存储应该在您的特定析构函数调用中幸存下来,即使在您的类是分配器的情况下也是可能的(通常设计不好,但允许(。
析构函数上下文只是";看到";成员,在这种情况下,这只是一个先验的指针,而不是可能进一步动态分配的资源。请尝试熟悉重要的RAII技术,它不仅与动态内存分配有关。