在C++中,当对象的指针超出作用域时,为什么不能释放对象?

vlju58qv  于 2022-11-19  发布在  其他
关注(0)|答案(2)|浏览(202)

假设我有一个方法,那么new一个对象在这个方法里面:

void MyMethod() {
  Obj* p = new Obj();
}

当函数结束时,指针会被删除,因为它超出了作用域,如果我没有返回p指针,这意味着没有引用这个Obj对象,为什么编译器不能为我们删除对象呢?
因此,如果人们忘记这样做,就不会出现“内存泄漏”。

ijxebb2r

ijxebb2r1#

它可以用std::unique_ptr!原始指针并不适合现代C++中的日常使用,您需要这样做:

#include <memory>

void MyMethod() {
  std::unique_ptr<Obj> p = std::make_unique<Obj>();
   // no leak!
}

或者你也可以只做Obj p;,但我想你知道。

k97glaaz

k97glaaz2#

在编译时确定指针是否超出范围是非常困难的。
假设您有这样的代码:

void bar(Obj* obj); //we do not know what this method does

int MyMethod() {
  Obj* obj = new Obj();
  bar(obj);
}

可以删除MyMethod末尾的obj吗?答案是否定的,因为bar()可能仍在使用它。例如,bar可能如下所示:

void* someGlobalVariable;

void bar(Obj* obj) {
  someGlobalVariable = (void*) obj;
}

那么MyMethod可能不会删除该对象,因为它仍在someGlobalVariable中使用。bar()也可能不会删除该对象,因为您不希望方法在您不期望的情况下随机释放传递给它们的内存。因此,编译器在这里无法帮助您,您需要自己管理内存。
一般来说,我们希望最终释放我们分配的所有内存。由于编译器不能为我们做到这一点(至少不总是这样),我们需要手动完成。现在,我们可以设计一个编译器,它有一些规则,当它自动插入代码删除指针。
但是这样的编译器在实际使用中会很麻烦,因为你总是需要记住编译器为你删除内存的规则,而不是你需要自己删除内存的规则。如果你让编译器更聪明,你就会让现有的程序出错。所以C语言的设计者们选择了一致的选项:“你必须总是释放你自己分配的所有内存”。

相关问题