我已经习惯了c ++一段时间了,来自java的一个最混乱的方面就是内存管理。例如,假设我有一个方法,并且在该方法中我声明了一个指向对象的指针,我想使用get方法将该指针设置为另一个对象的属性:
SubObject *mySubObject = anotherObject.getSubObject();
我的问题是,当方法结束时,该指针会发生什么?我应该在它结束之前使用以下内容吗?
delete mySubObject;
如果我不删除该怎么办?它会一直持续到整个程序结束吗?
我已经尝试使用谷歌搜索c ++的基本内存管理教程,但我通常会发现更多高级内容,这些内容都会超出我的想法。
答案 0 :(得分:9)
跟踪内存管理可能是一种负担,最好的建议是尽可能避免它并通过避免原始指针使其明确。如果您只需要临时访问其他位置的变量(在您的示例中,它是不同对象的成员,并因此在那里进行管理)您不应该delete
它,如果您更好只需持有reference
而不是指针,因为引用明确表明您没有管理该资源。
答案 1 :(得分:3)
如果getSubObject()
方法只返回指向先前分配的mySubObject的指针,则不应删除它,因为这应该是首先分配它的类的责任。此指针甚至可能没有通过new
分配并且在堆栈中,因此删除它可能会导致更大的问题。
根据经验,delete
你拥有new
'd。当然,这在很大程度上取决于编程的布局。
答案 2 :(得分:3)
要回答帖子标题中的问题,当且仅当您使用delete[]
分配内存时,才应使用new[]
。当且仅当您使用delete
分配内存时,才应使用new
。
int *array = new int[10];
int *ptr = new int;
...
delete[] array;
delete ptr;
要回答您的帖子,您应该问自己代码何时分配内存。实际上,您应该将内存视为资源,例如文件句柄或网络连接。无论何时用C ++或Java打开文件,完成后都应关闭文件。同样,无论何时在C ++中分配内存,都应该释放它。困难的问题是你何时应该释放记忆。方法也是如此
anotherObject.getSubObject();
返回指向新分配对象的指针?它的工作是释放上述方法返回的指针所指向的内存吗?
如果上面的方法使用new
并返回指向新分配的内存的指针,则客户端(调用该方法的程序员)必须delete
内存。但是,如果方法返回的指针在调用析构函数时被对象anotherObject
释放,则客户端不应释放指针引用的内存。
如果您不熟悉Java中的C ++,请尽可能使用references,并查看smart pointers。智能指针的好处在于它们提供了自动内存管理(在new
编辑对象后,您不必担心删除。
答案 3 :(得分:1)
回答主题中的问题:在C ++中,使用delete []删除用new []分配的数组。即:
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正确地指出删除调用中[]的原因是为了确保在数组的每个元素中调用析构函数。
答案 4 :(得分:1)
当您尝试学习基本的C ++内存管理时,请忘记有关引用和智能指针的所有答案。
了解基础知识,稍后您可以返回这些“高级”科目。
答案 5 :(得分:0)
在不了解getSubObject()
的详细信息的情况下,无法知道如何真正回答这个问题。答案应位于getSubObject()
的文档中(但不是每个人都遵循应该。)该文档可能在某些旧式文档中,有些是doxygen(或类似的)页面,声明getSubObject()
的头文件。如果最坏的情况发生,您需要查看定义getSubObject()
的源代码,假设源是可用的。
在阅读该文档/标题/来源时,您应该寻找问题的答案“是getSubObject()
分配调用者必须删除的内存,还是只返回指向现有对象的指针?”使用getSubObject()
之类的名称,我希望后者就是这种情况。如果函数的名称为createSubObject()
,我会期待前者。
答案 6 :(得分:0)
没有正确答案。 如果成员函数(或者我们使用java术语的方法)返回的指针指向堆栈中分配的对象,如果在其上使用关键字delete,程序将崩溃。
如果您使用免费存储空间,来电者或被叫者是否应负责内存管理?如果另一个人调用成员函数,现在你有一个悬空指针。如果被叫方使用 RAII 会怎样?
由于您正在学习(为此而感到荣誉),请先尝试学习内存管理的基础知识。一旦你对内存有了基本的了解,你就会更加熟悉C ++和内存管理。
如果您正在使用生产代码,则必须在C ++中执行此操作。避免所有这些问题最安全的方法是仅在需要时使用动态内存分配,直到您对其有更好的理解。在我看来,即使你对动态内存分配有很好的理解,你也应该有充分的理由使用它。
祝你好运,阿曼。
答案 7 :(得分:0)
在C ++中,你必须自己管理内存分配,没有垃圾收集你忘记清理java / C#和任何其他现代语言。如果你忘记了记忆,最好是泄露,最坏的情况是你继续使用它而其他的东西。这是一个很难解决的问题,很少有人,如果有的话,C ++程序员可以做到这一点,因此需要使用智能指针和其他深奥的高级魔术来解决C ++中的这些问题。 @yi_H是正确的,了解基本内存分配的基础知识,所以你知道为什么Smart Pointers是个好主意。
如果没有智能指针,虽然上面的一些答案已经躲过了,但“所有权”是最重要的理解。每当你有一个指向内存块的指针时,你必须知道谁拥有它。如果你拥有它,你必须在它超出范围之前释放它或它丢失。如果您给别人一份副本,请确保您定义谁拥有它,以及何时所有者可以/将/应该释放它。如果你做不到这一点,你就会受到冲击。作为一项规则,C ++库在记录时非常糟糕,因此在没有明确信息的情况下,假设您不拥有它(不要删除它并可能造成内存泄漏),而不是删除它并创建难以发现的缺陷。使用Valgrind查找工作程序中的内存泄漏。
为避免最严重的陷阱,请遵守一些简单的规则。使用本地和引用优先于heap(new)。返回已分配的内存时,请清楚地记录已分配内存的所有权和生命周期。避免复制指向已分配内存的指针,尽可能复制数据。制作指针副本时,可以使范围尽可能小而短。指针的大量使用(以糟糕的方式)以效率的名义进行 - 运行缓慢的程序比随机核心转储的程序更有效。
即。限制使用关键字“new”。
答案 8 :(得分:0)
设计不应该是这样的,你从另一个对象得到一个指针并删除它。
SubObject *mySubObject = anotherObject.getSubObject();
delete mySubObject;
如果在该点删除mySubObject,则另一个类类函数仍可以使用它。你应该遵循OOP方法。 getSubObject()函数返回的对象应该从构造函数创建/分配内存并在析构函数中释放。是的,参考在这里更好,所以错误地在课外不执行删除。感谢。