何时删除[]指针c++

When to delete[] a pointer c++?

本文关键字:指针 c++ 删除 何时      更新时间:2023-10-16

我玩c++已经有一段时间了,来自java的我最困惑的方面之一是内存管理。例如,假设我有一个方法,在该方法中,我声明了一个指向对象的指针,我想使用get方法将该指针设置为另一个对象的属性:

SubObject *mySubObject = anotherObject.getSubObject();

我的问题是,当方法结束时,这个指针会发生什么?我应该在它结束之前使用以下内容吗?

delete mySubObject;

如果我不删除它怎么办?它会一直保留到整个程序结束吗?

我试过在谷歌上搜索c++的基本内存管理教程,但我通常会发现更高级的东西,这让我难以想象,任何引用都会受到赞赏。

跟踪内存管理可能是一种负担,最好的建议是尽可能避免它,并通过避免原始指针来明确它。如果您只需要临时访问一个保存在其他地方的变量(在您的示例中,它是另一个对象的成员,因此在那里进行管理),则不应该delete它,如果您只保存reference而不是指针会更好,因为引用明确表示您没有管理该资源。

如果getSubObject()方法只是返回一个指向以前分配的mySubObject的指针,则不应删除它,因为这应该是首先分配它的类的责任。此外,该指针可能甚至没有通过new分配,也不在堆栈中,因此删除它可能会导致更大的问题。

根据经验,delete等于new。当然,这在很大程度上取决于程序的布局。

要回答文章标题中的问题,您应该使用delete[],当且仅当您使用new[]分配内存时。当且仅当您使用new来分配内存时,才应使用delete

int *array = new int[10];
int *ptr = new int;
...
delete[] array;
delete ptr;

要回答您的帖子,您应该问问自己代码何时分配内存。事实上,您应该将内存视为一种资源,就像文件句柄或网络连接一样。任何时候用C++或Java打开一个文件,完成后,都应该关闭这些文件。同样,在C++中分配内存的任何时候,都应该释放内存。棘手的问题是什么时候释放内存。方法也是如此

anotherObject.getSubObject();

是否返回指向新分配对象的指针?释放上面方法中返回的指针所指向的内存是谁的工作?

如果上面的方法使用new并返回一个指向新分配的内存的指针,那么客户端(调用该方法的程序员)必须delete内存。但是,如果方法返回的指针在调用其析构函数时由对象anotherObject释放,则客户端不应释放指针引用的内存。

如果您是Java中的C++新手,那么您应该尽可能尝试使用引用,并检查智能指针。智能指针的好处在于,它们提供了自动内存管理(在new编辑对象后,您不必担心删除)。

当你只是想学习基本的C++内存管理时,忘记所有关于引用和智能指针的答案。

学习基础知识,以后你可以回到这些"高级"科目。

要回答主题中的问题:在C++中,您可以使用delete[]删除分配有new[]的数组。Ie:

int *a = new int[10];  // Allocate 10 ints and save ptr in a.
for (int i=0; i<10; i++) {
    a[i] = 0;    // Initialize all elements to zero.
}
delete [] a; // Free memory allocated for the a array.

正如Gustavo正确指出的那样,删除调用中[]的原因是为了确保在数组的每个元素中都调用析构函数。

如果不了解getSubObject()的详细信息,就无法知道如何真正回答这个问题。答案应该getSubObject()的文档中(但并不是每个人都遵循。)该文档可能在某个旧式文档、某个doxygen(或类似)页面中,即声明getSubObject()的头文件中。如果最坏的情况出现,您需要查看定义getSubObject()的源代码,假设源代码可用。

在阅读该文档/header/source时,您应该寻找"getSubObject()是分配调用方必须删除的内存,还是只返回一个指向现有对象的指针?"对于getSubObject()这样的名称,我希望是后者。如果函数的名称是createSubObject(),我会期望前者。

对此没有正确的答案如果成员函数(或方法,如果我们使用的是java语言)返回的指针指向堆栈中分配的对象,如果在其上使用关键字delete,您的程序将崩溃。

如果您使用空闲存储调用者或被调用者是否应该负责内存管理?如果另一个人调用成员函数,现在您有一个悬空指针。如果被叫方正在使用RAII,该怎么办?

既然你正在学习(这值得称赞),那就试着先学习记忆管理的基础知识。一旦你对内存有了基本的了解,你就会对C++和内存管理更加得心应手。

如果你正在做生产代码,并且你必须用C++来做。避免所有这些问题的最安全的方法是只在需要的时候使用动态内存分配,直到你对它有了更好的理解。在我看来,即使你对动态内存分配有了很好的理解,你也应该有一个很好的理由来使用它。

祝你好运,

阿曼多。

在C++中,您必须自己管理内存分配,没有像java/C#和任何其他现代语言那样忘记清理的垃圾位。如果你失去了对内存的跟踪,往好了说是内存泄露了,往坏了说是在其他事情发生时继续使用它。这是一个很难解决的问题,如果有的话,很少有C++程序能解决这个问题,所以在C++中使用智能指针和其他深奥的高级魔法来解决这些问题@yi_H是正确的,了解基本内存分配的基础知识,这样你就知道为什么智能指针是一个好主意了。

如果没有聪明的指针,尽管上面的一些答案都无法找到,但"所有权"是最重要的理解。每当你有一个指向内存块的指针时,你必须知道谁拥有它。如果你拥有它,你必须在它超出范围或丢失之前将其释放。如果你给别人一份,请确保你定义了谁拥有它,以及所有者何时可以/将/应该释放它。如果你不能做到这一点,你就会被解雇。通常,C++库在记录这一点方面是出了名的不好,所以在缺乏明确信息的情况下,假设你不拥有它(不要删除它,可能会造成内存泄漏),而不是删除它并创建难以找到的缺陷。使用Valgrind查找工作程序中的内存泄漏。

为了避免最坏的陷阱,请遵守一些简单的规则。使用局部和引用优先于堆(new)。返回已分配内存时,请清楚地记录已分配内存的所有权和生命周期。避免复制指向已分配内存的指针,尽可能复制数据。在复制指针时,应使作用域尽可能小且使用寿命短。指针的大量使用(糟糕地)是以效率的名义进行的——运行缓慢的程序比随机核心转储的程序效率高得多。

即限制使用关键字"new"。

好吧,设计不应该是这样的,你从另一个对象中获取一个指针并将其删除。

SubObject *mySubObject = anotherObject.getSubObject();
delete mySubObject;

如果在这一点上删除mySubObject,其他Object类函数可能仍在使用它。您应该遵循OOP方法。getSubObject()函数返回的对象应该从构造函数创建/分配内存,并在析构函数中释放。这里的yes引用更好,这样就不会在类外错误地执行删除。谢谢