简体   繁体   English

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

[英]C++ objects lifetime on stack and heap

I'm trying to translate some projects I've made with Delphi; 我正在尝试翻译我用Delphi制作的一些项目; an object can be declared in general as: 一般来说,对象可以声明为:

//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;

Reading Stroustrup's book about C++ I have understood that (in short) his language doesn't need the finally block because there are always workarounds. 阅读Stroustrup关于C ++的书我已经理解(简而言之)他的语言不需要finally块,因为总有解决方法。 Now if I want to create a class I have two ways: 现在,如果我想创建一个类,我有两种方法:

  1. THuman male; in which the object is created and then goes out of scope when the block {... code ...} ends 在块{... code ...}结束时创建对象然后超出范围的对象

  2. THuman* male = new THuman I can control the object's life and destroy it with a delete THuman* male = new THuman我可以控制对象的生命并用delete摧毁它


The book suggests to use the first approach (even if both are fine) but I come from a Delphi background and I want to use the second method (I have the control of the object). 本书建议使用第一种方法(即使两者都很好),但我来自Delphi背景,我想使用第二种方法(我有对象的控制)。

Questions. 问题。 I cannot understand the difference between the 2 methods that C++ have for objects and reading online I got more confusion. 我无法理解C ++对于对象和在线阅读的两种方法之间的区别我有更多的困惑。 Is it correct if I say that method 1 allocates memory on the stack and method 2 on the heap? 如果我说方法1在堆栈上分配内存并在堆上分配方法2,这是正确的吗?

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? 在方法2(我们在堆中)如果我将值NULL赋给对象,我是否仍然需要调用删除?

For example Delphi allows to create instances only on the heap and the Free deletes the object (like delete in C++). 例如,Delphi只允许在堆上创建实例,而Free删除对象(如C ++中的delete )。

In Short 简而言之

1- Objects not created with new have automatic lifetime (created in the stack as you say, but that is an implementation technique chosen by most compilers), they are automatically freed once they go out of scope. 1-没有使用new创建的对象具有自动生命周期(如您所说,在堆栈中创建,但这是大多数编译器选择的实现技术),一旦超出范围,它们将自动释放。

2- The lifetime of objects created with new (created in the heap, again as an implementation technique of most compilers), need to be managed by the programmer. 2-用new创建的对象的生命周期(在堆中创建,再次作为大多数编译器的实现技术)需要由程序员管理。 Notice that deleting is NOT setting the pointer to NULL, it should happen before. 请注意,删除不是将指针设置为NULL,它应该在之前发生。 The simple rule is: 简单的规则是:

  • Each new must be matched with one an only one delete 每个new必须匹配一个只有一个delete
  • each new[] (creation of dynamic arrays) must be matched with one an only one delete[] 每个new[] (创建动态数组)必须匹配一个只有一个delete[]

ps: matched here concerns one-vs-one occurrence in the program's runtime, not necessarily in the code itself (you have control over when and where to delete any newed object). ps: 匹配在这里涉及程序运行时中的一对一出现,不一定在代码本身中(您可以控制删除任何对象的时间和位置)。

Is it correct if I say that method 1 allocates memory on the stack and method 2 on the heap? 如果我说方法1在堆栈上分配内存并在堆上分配方法2,这是正确的吗?

  • Yes

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? 在方法2(我们在堆中)如果我将值NULL赋给对象,我是否仍然需要调用删除?

  • Consider using smartpointers instead of raw pointers. 考虑使用smartpointers而不是原始指针。 Smartpointers are objects which handle pointer resources and make them more safe to use. Smartpointers是处理指针资源并使其更安全使用的对象。 However, if you cannot use smart pointers, make sure to call delete on the pointer to release the previous allocated memory from the heap before you assign NULL to it. 但是,如果您不能使用智能指针,请确保在指针上调用delete以从堆中释放先前分配的内存,然后再为其指定NULL Otherwise you will have leaked resources. 否则你会泄露资源。 To check your program memory management you can run valgrind 要检查程序内存管理,可以运行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? 在方法2(我们在堆中)如果我将值NULL赋给对象,我是否仍然需要调用删除?

if you do this before calling delete you leaked memory and if you call delete on a NULL pointer you get a seg fault(application crash). 如果在调用delete之前执行此操作,则泄漏内存,如果在NULL指针上调用delete,则会出现seg错误(应用程序崩溃)。

the best way is to use stack objects, but if you need to manage object's existence use smart pointer(unique_ptr, shared_ptr) as suggested above. 最好的方法是使用堆栈对象,但如果需要管理对象的存在,请使用上面建议的智能指针(unique_ptr,shared_ptr)。

Note : by "Leaked memory" I mean that this region is lost it cannot be accessed from program , nor freed by OS. 注意:“泄漏内存”是指该区域丢失,无法从程序访问,也无法通过操作系统释放。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM