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