假设我有一个方法,那么new一个对象在这个方法里面:
new
void MyMethod() { Obj* p = new Obj(); }
当函数结束时,指针会被删除,因为它超出了作用域,如果我没有返回p指针,这意味着没有引用这个Obj对象,为什么编译器不能为我们删除对象呢?因此,如果人们忘记这样做,就不会出现“内存泄漏”。
p
Obj
ijxebb2r1#
它可以用std::unique_ptr!原始指针并不适合现代C++中的日常使用,您需要这样做:
std::unique_ptr
#include <memory> void MyMethod() { std::unique_ptr<Obj> p = std::make_unique<Obj>(); // no leak! }
或者你也可以只做Obj p;,但我想你知道。
Obj p;
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可能如下所示:
MyMethod
obj
bar()
bar
void* someGlobalVariable; void bar(Obj* obj) { someGlobalVariable = (void*) obj; }
那么MyMethod可能不会删除该对象,因为它仍在someGlobalVariable中使用。bar()也可能不会删除该对象,因为您不希望方法在您不期望的情况下随机释放传递给它们的内存。因此,编译器在这里无法帮助您,您需要自己管理内存。一般来说,我们希望最终释放我们分配的所有内存。由于编译器不能为我们做到这一点(至少不总是这样),我们需要手动完成。现在,我们可以设计一个编译器,它有一些规则,当它自动插入代码删除指针。但是这样的编译器在实际使用中会很麻烦,因为你总是需要记住编译器为你删除内存的规则,而不是你需要自己删除内存的规则。如果你让编译器更聪明,你就会让现有的程序出错。所以C语言的设计者们选择了一致的选项:“你必须总是释放你自己分配的所有内存”。
someGlobalVariable
2条答案
按热度按时间ijxebb2r1#
它可以用
std::unique_ptr
!原始指针并不适合现代C++中的日常使用,您需要这样做:或者你也可以只做
Obj p;
,但我想你知道。k97glaaz2#
在编译时确定指针是否超出范围是非常困难的。
假设您有这样的代码:
可以删除
MyMethod
末尾的obj
吗?答案是否定的,因为bar()
可能仍在使用它。例如,bar
可能如下所示:那么
MyMethod
可能不会删除该对象,因为它仍在someGlobalVariable
中使用。bar()
也可能不会删除该对象,因为您不希望方法在您不期望的情况下随机释放传递给它们的内存。因此,编译器在这里无法帮助您,您需要自己管理内存。一般来说,我们希望最终释放我们分配的所有内存。由于编译器不能为我们做到这一点(至少不总是这样),我们需要手动完成。现在,我们可以设计一个编译器,它有一些规则,当它自动插入代码删除指针。
但是这样的编译器在实际使用中会很麻烦,因为你总是需要记住编译器为你删除内存的规则,而不是你需要自己删除内存的规则。如果你让编译器更聪明,你就会让现有的程序出错。所以C语言的设计者们选择了一致的选项:“你必须总是释放你自己分配的所有内存”。