如何正确删除 C++ 中的指针? [复制]
Posted
技术标签:
【中文标题】如何正确删除 C++ 中的指针? [复制]【英文标题】:How to delete a pointer in C++ properly? [duplicate] 【发布时间】:2020-06-19 04:17:06 【问题描述】:我是 C++ 新手,我有一个问题。
假设您使用以下代码声明了变量 x
:
MyClass *x = new MyClass();
使用这个变量后,我不再需要它了。
在以下命题中,那么首选的行动方案是什么?有什么区别?
致电free(x);
致电x->~MyClass();
致电MyClass::~MyClass(p);
致电delete x;
谁能帮我理解这个?
提前致谢。
【问题讨论】:
用new
创建的变量应该用delete
删除
首选的做法是首先不要写MyClass *x = new MyClass();
,而是MyClass x;
,或者如果您确实需要动态分配,请使用智能指针
请使用 std::make_uniquenew
。而是使用std::unique_ptr<T> var = std::make_unique<T>();
@RamblinRose 这不是重复的,它是关于放置新的
【参考方案1】:
如果您通过new
创建实例:
MyClass *x = new MyClass();
您必须通过delete
删除它:
delete x;
1.) 致电
free(x);
没有。 free
只释放它不调用析构函数的内存。如果你malloc
内存你需要free
它,但是你很少在C++中使用malloc
并且在从new
获得的指针上调用free
是错误的。
2.) 致电
x->~MyClass();
没有。显式调用析构函数几乎总是错误的!
(例如,当您通过placement new 创建对象时,您不会直接调用delete
,而是直接调用析构函数,因为placement new 会在已分配的内存中创建对象。)
3.) 致电
MyClass::~MyClass(p);
没有。这是没有意义的,析构函数不带参数。
4.) 致电
delete x;
是的。 Calling delete
...
销毁以前由新表达式分配的对象并释放获得的内存区域
但是你不应该手动管理内存。要么依赖自动存储:
MyClass x;
x
的析构函数在超出范围时被自动调用。或者,如果您确实需要动态内存分配,请使用 smart pointers。
进一步阅读:Why should C++ programmers minimize use of 'new'?
顺便说一句,这是一个常见的误解,以至于我记得每一次关于 Stroustrup 的演讲都有一个使用new
创建对象的示例,然后他解释说绝对不应该使用new
。实际上,除了忘记打电话给delete
之外,还有更多的事情要做。考虑:
MyClass *x = new MyClass();
foo();
delete x; // phew I didnt forget to call delete
如果foo
抛出异常,则此代码会泄漏内存。正确的做法是依靠RAII:
MyClass x;
foo();
现在如果foo
抛出异常,x
的析构函数将被调用!
【讨论】:
我同意删除部分。除此之外,在我的公司内,始终让这个指针指向 0 是一种惯例,例如delete x; x = 0;
@dejoma 巧合的是,我最近回答了一个关于此的问题。将指针设置为nullptr
有一个(有限的)用途,但它的主要效果是一种虚假的安全感。见这里:***.com/a/60522321/4117728。它不能解决手动使用new
和delete
带来的一般问题
除此之外,在我的公司内部,总是让这个指针指向 0 是一种惯例——我知道这有什么影响只有一个原因—— 0 指针表示需要分配对象。如果像这样使用它:if (ptr != nullptr) delete ptr;
可以完全删除对 nullptr 的检查,因为删除 nullptr 是完全有效的。如果使用它是因为您的程序流程发生了很多曲折以至于您不知道指针的状态,那么可能需要审查代码。
"如果您通过new
创建实例...您必须通过delete
删除它" - 除非您使用placement-new
,否则不要完全使用delete
,你必须直接调用类型的析构函数ala #2
@RemyLebeau 谢谢,添加了注释。我认为“如果......你必须”仍然很好,因为它指的是 OP 代码【参考方案2】:
使用new
关键字动态分配的变量应使用delete
关键字删除。 new
和delete
调用指定类的构造函数和析构函数。这意味着您的实例已正确初始化和取消初始化。
所以,用MyClass *x = new MyClass();
初始化的实例x
应该用delete x;
删除。
但是,如果可能的话,最好在堆栈上声明变量,如 MyClass x;
并让 RAII 完成它的工作。看看下面的例子:
// creates an object 'x' on stack
MyClass x;
// do something with 'x'
// once the object is out of scope, it is automatically being destructed
此外,如果您仍需要动态分配,现代 C++ 建议使用智能指针,例如 std::shared_ptr
和 std::unique_ptr
。智能指针会自动代替您处理内存。换句话说,通过使用智能指针,您无需关心delete
ing 使用new
创建的对象。你可以这样写:
// creates an object 'x' on heap
// its default ctor is being called
std::shared_ptr<MyClass> x = std::make_shared<MyClass>();
// once the object is out of scope, even though it is allocated
// on the heap, there is no need to call 'delete' here because
// deletion is automatically handled by the 'std::shared_ptr'
【讨论】:
请注意,RAII 的重点是x
无论如何都会被销毁,即使存在异常(或return
),如果范围将始终保留在
那么实际使用new
和delete
就不会那么重要了。刚刚意识到您的“//一旦对象超出范围”表明您始终将范围留在
,因为我最终得到了与您类似的示例。无论如何,你有我的 +1,
@idclev463035818 是的,感谢您指出这一点。无论如何,你也有我的 +1。以上是关于如何正确删除 C++ 中的指针? [复制]的主要内容,如果未能解决你的问题,请参考以下文章