为什么必须为存储在堆中的函数的局部变量调用delete?

jsg*_*guy 6 c++ memory memory-leaks

假设您具有以下功能:

 void doSomething(){
    int *data = new int[100];
 }
Run Code Online (Sandbox Code Playgroud)

为什么会产生内存泄漏?由于我无法在函数外部访问此变量,为什么每次调用此函数时编译器都不会自行调用delete?

Mik*_*our 9

为什么会产生内存泄漏?

因为您负责删除您创建的任何内容new.

为什么每次调用此函数结束时编译器都不会自行调用delete?

通常,编译器无法判断您是否仍具有指向已分配对象的指针.例如:

void doSomething(){
    int *data = new int[100];
    doSomethingElse(data);
}
Run Code Online (Sandbox Code Playgroud)

难道doSomethingElse只是使用指针的函数调用时(在这种情况下,我们还是要在这里删除阵列)?它是否存储指针的副本以供以后使用(在这种情况下我们不想删除它)?编译器无法知道; 你可以告诉它.而不是制作一个复杂的,容易出错的规则(比如"你必须删除它,除非你能弄清楚编译器必须知道没有其它的引用"),规则很简单:你必须删除它.

幸运的是,我们可以做得更好,而不是玩杂耍原始指针并尝试在正确的时间删除它.RAII的原理允许对象获取已分配资源的所有权,并在它们超出范围时调用析构函数时自动释放它们.容器允许动态对象在单个范围内维护,并在需要时复制; 智能指针允许在范围之间移动或共享所有权.在这种情况下,一个简单的容器将为我们提供一个动态数组:

void doSomething(){
    std::vector<int> data(100);
} // automatically deallocated
Run Code Online (Sandbox Code Playgroud)

当然,对于像这样的小型固定大小的数组,您可能只需将其自动化:

void doSomething(){
    int data[100];
} // all automatic variables are deallocated
Run Code Online (Sandbox Code Playgroud)


Bau*_*gen 5

像这样的动态分配的全部要点是您手动控制分配对象的生命周期.这是需要和适当一个很多不经常比许多人似乎认为.事实上,我想不出有效的用法new[].

让编译器处理对象的生命周期确实是一个好主意.这称为RAII.在这种特殊情况下,您应该使用std::vector<int> data(100).现在,只要data超出范围,内存就会自动释放.

  • @Guiroux按值返回向量. (3认同)
  • @Guiroux不,我们有[RVO](https://en.wikipedia.org/wiki/Return_value_optimization)并移动作业.如果您是C++ 11之前的版本,那么`std :: vector <int>&`输入参数*可能是最佳选择,具体取决于具体情况. (3认同)