简体   繁体   English

即使指针在函数堆栈中,我也必须删除它吗?

[英]Do I have to delete pointer even if it is in function stack?

always delete pointer even if it is just in function call stack? 总是删除指针,即使它只是在函数调用堆栈中? Isn't it disappeared when function stack released? 函数栈释放时它不消失了吗?

// just Simple class
class CSimple{
  int a;
}

// just simple function having pointer.
void simpleFunc(){  
  CSimple* cSimple = new CSimple();
  cSimple->a = 10;
  //.. do sth
  delete cSimple;  // <<< Always, do I have to delete 'cSimple' to prevent the leak of memory?
}

void main(){
  for( int =0 ; i< 10 ; i++){
     simpleFunc();
  }

}

when function stack released? 函数堆栈何时释放?

It is true that "CSimple *csimple" goes away when the function returns. 当函数返回时,“ CSimple * csimple”确实消失了。

However, there's a big difference between the pointer, and what it's pointed to. 但是,指针与其指向的对象之间存在很大差异。

When a pointer object gets destroyed, nothing happens to whatever the pointer is pointing to. 当指针对象被销毁时,指针所指向的内容什么也没有发生。 There isn't just one, but two objects here: 这里不仅有一个,而且还有两个对象:

  1. The pointer. 指针。

  2. What it's pointing to. 它指向的是什么。

In this case, the pointer is pointing to an object in dynamic scope that was created with new . 在这种情况下,指针指向使用new创建的动态范围内的对象。

Nothing is going to happen to this object, otherwise, so you will leak memory. 该对象什么也不会发生,否则,您将泄漏内存。

Therefore, this object needs to be delete d. 因此,该对象需要delete d。

After you understand, and fully wrap your brain around this concept, your next step will be to open your C++ book to the chapter that talks about the std::unique_ptr and std::shared_ptr classes, which will take care of these pesky details, for you. 了解并充分理解这个概念之后,下一步就是打开C ++书籍,进入有关std::unique_ptrstd::shared_ptr类的章节,这将处理这些令人讨厌的细节,为了你。 You should learn how to use them. 您应该学习如何使用它们。 Modern C++ code rarely needs to delete something; 现代的C ++代码很少需要delete某些内容。 rather these smart pointers do all the work. 这些智能指针可以完成所有工作。

Yes. 是。

On scope exit (ex. when function exists or block { ... } finishes), all objects created on stack will be destroyed and memory will be freed. 在范围退出时(例如,当函数存在或块{...}完成时),在堆栈上创建的所有对象将被销毁,内存将被释放。

This applies to your case, ie. 这适用于您的情况,即。 the pointer will be destroyed and memory occupied by the pointer will be freed. 指针将被销毁,并且指针所占用的内存将被释放。 The object pointed by the pointer will not be cleared. 指针指向的对象将不会被清除。

This is a common problem and a nightmare when you deal with multiple flow paths (if-else ladders, many return statements) and exceptions. 当您处理多个流路径(if-else阶梯,许多return语句)和异常时,这是一个普遍的问题,也是一场噩梦。

To solve this problem, we employ 2 main strategies: 为了解决这个问题,我们采用了两种主要策略:

  1. RAII RAII
  2. Smart pointers ( std::unique_ptr , boost::scoped_ptr , legacy std::auto_ptr , etc). 智能指针( std::unique_ptrboost::scoped_ptr ,旧版std::auto_ptr等)。

RAII - without academic consideration - is just creating object on stack, like this: RAII-无需学术考虑-只是在堆栈上创建对象,如下所示:

{
   std::string s;
   fancy_object obj;
}

When we exit he scope, obj and s destructors will be called duing stack unwinding. 当我们退出他的作用域时, objs析构函数将被称为duing stack unwinding。 Compiler ensures this for all flow paths and will keep proper order of deallocations for us. 编译器会确保所有流路都如此,并会为我们保持正确的释放顺序。

If you need to allocate memory on heap, using new , use a smart pointer. 如果需要在堆上分配内存,请使用new ,请使用智能指针。

int foo()
{
    std::unique_ptr<Object> o(new Object);
    ... some more code ...
    if( something ) { return -1 }
    ... some more code ...
    if( something_else ) { return -2 }
    else { not yet }
    return 0;
}

As you can see, we can leave the scope using 3 "exists". 如您所见,我们可以使用3个“ exists”离开范围。 Normally, you'd need to clear your memory in all cases, which is prone to human errors. 通常,在所有情况下都需要清除内存,这很容易导致人为错误。

Instead of clearing the object manually in all 3 palces, we rely on automatic destructor call for objects created on stack. 无需在所有3种情况下手动清除对象,而是依靠自动析构函数调用堆栈上创建的对象。 Compiler will figure it out. 编译器会解决。 When we leave the scope, std::unique_ptr destructor will be called, calling delete on Object . 当我们离开范围时,将调用std::unique_ptr析构函数,并在Object上调用delete

Don't be affraid of smart poiners. 不要被聪明的笨蛋所宠爱。 They are not "slow", "bloat" or other nonsense. 它们不是“慢”,“膨胀”或其他废话。 Smart poiners are designed to have no overhead on access, adding extra security. 智能Poiners的设计没有访问开销,从而增加了额外的安全性。

Very similar technique is used for locks. 非常类似的技术用于锁。 Check out std::lock_guard class. 查看std::lock_guard类。

Yes, you must delete the data that is being pointed to. 是的,您必须delete所指向的数据。

The pointer itself is on the stack and does not need to be deleten. 指针本身在堆栈上,不需要删除。

You can, however, store cSimple on the stack, then you don't have to delete it: 但是,您可以将cSimple存储在堆栈中,然后不必删除它:

void simpleFunc(){  
  CSimple cSimple; // no new
  cSimple.a = 10; // "." instead of "->"
  //.. do sth
  // no deletion
}

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

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