C++ 对象在堆栈和堆上的生命周期

C++ objects lifetime on stack and heap

我正在尝试翻译我用 Delphi 制作的一些项目;一个对象通常可以声明为:

//I have the control of the object and I MUST delete it when it's not needed anymore

male := THuman.Create();
try
 // code
finally
 male.Free; (get rid of the object)
end;

阅读 Stroustrup 关于 C++ 的书我了解到(简而言之)他的语言不需要 finally 块,因为总是有解决方法。现在如果我想创建一个 class 我有两种方法:

  1. THuman male; 对象在其中创建,然后在块 {... code ...} 结束时超出范围

  2. THuman* male = new THuman我可以控制对象的生命并用delete

  3. 摧毁它

书上建议使用第一种方法(即使两者都可以),但我来自 Delphi 背景,我想使用第二种方法(我有对象的控制权)。

问题。我无法理解 C++ 对象的两种方法之间的区别,在线阅读时我更加困惑。如果我说方法1在栈上分配内存,方法2在堆上分配内存是否正确?

在方法2中(我们在堆中)如果我将值NULL赋给对象,我还需要调用删除吗?

例如 Delphi 只允许在堆上创建实例,而 Free 删除对象(类似于 C++ 中的 delete)。

Is it correct if I say that method 1 allocates memory on the stack and method 2 on the heap?

In method 2 (we're in the heap) if I assigned the value NULL to the object, do I still have to call the delete?

  • 考虑使用 smartpointers 而不是原始指针。智能指针是处理指针资源并使它们更安全使用的对象。 但是,如果您不能使用智能指针,请确保在向指针分配 NULL 之前调用指针 delete 以从堆中释放先前分配的内存。否则你会泄漏资源。要检查您的程序内存管理,您可以 运行 valgrind

In method 2 (we're in the heap) if I assigned the value NULL to the object, do I still have to call the delete?

如果您在调用 delete 之前执行此操作,则会泄漏内存,如果您在 NULL 指针上调用 delete,则会出现段错误(应用程序崩溃)。

最好的方法是使用堆栈对象,但如果您需要管理对象的存在,请按照上面的建议使用智能指针(unique_ptr、shared_ptr)。

注意:"Leaked memory" 我的意思是这个区域丢失了,它不能从程序访问,也不能被 OS 释放。

简而言之

1- 不是用 new 创建的对象具有自动生命周期(如您所说,在堆栈中创建,但这是大多数编译器选择的实现技术),一旦超出范围,它们就会自动释放.

2- 使用new创建的对象(在堆中创建,也是大多数编译器的一种实现技术)的生命周期需要由程序员管理。请注意,删除并不是将指针设置为 NULL,它应该发生在之前。简单的规则是:

  • 每个 new 必须与一个唯一的匹配 delete
  • 每个new[](动态数组的创建)必须与一个唯一的匹配delete[]

p.s: matched 这里关注的是程序运行时的一对一事件,不一定是代码本身(你可以控制何时何地删除任何 newed 对象)。