垃圾收集是否在标准C++中自动进行?

Bra*_*don 14 .net c++ garbage-collection

根据我的理解,在标准C++中,无论何时使用new运算符,您还必须在某些时候使用delete运算符来防止内存泄漏.这是因为C++中没有垃圾收集.在.NET中,垃圾收集是自动的,因此无需担心内存管理.我的理解是否正确?谢谢.

blw*_*y10 19

对它的长期回答是,每次new被调用,某个地方,某种程度上,delete必须被调用,或者一些其他的释放函数(取决于内存分配器等)

但是您不需要成为提供delete呼叫的人:

  1. Hans-Boehm垃圾收集器的形式存在C++的垃圾收集.还可能有其他垃圾收集库.
  2. 您可以使用智能指针,它使用RAII(如果指针允许共享访问,则引用计数)以确定何时删除对象.一个好的智能指针库是Boost的智能指针.绝大多数情况下的智能指针可以替换原始指针.
  3. 一些应用程序框架(如Qt)构建对象树,因此框架的堆分配对象存在父子关系.因此,所有需要的是delete在一个对象上调用它,并且它的所有子节点也将自动被调用delete.

如果您不想使用这些技术中的任何一种,为了防止内存泄漏,您可以尝试使用内存检查工具.Valgrind特别好,虽然它只适用于Linux

对于.NET,是的,分配使用gcnew意味着内存由.NET跟踪,因此没有泄漏.但是,其他资源(如文件句柄等)不由GC管理.

  • RAII的一个优点(!)是您可以管理内存以外的资源,例如文件句柄.删除对象,同样关闭对象拥有的文件. (6认同)

nob*_*bar 9

惯用的高级C++中,您永远不会调用delete.

C++没有与C#中相同的标准垃圾收集器,因此从根本上说,newdelete需要配对.但是,C++中有一些机制完全消除了用现代风格编写的代码的明确用法delete.

首先要注意的是,在C++中,使用new 频率远低于new在C#中使用的频率.这是因为在C#中,new无论何时创建结构,类或数组的实例,都会使用它,但在C++中,new只有在想要动态管理数据元素时才使用.C++中的大多数数据不需要动态管理,因此可以在不使用的情况下创建new.[换句话说new,C#中的含义与C++中的含义不同.在C++中,它专门表示动态分配,而在C#中,它用于任何构造.

其次,无论new何时使用C++ 调用,返回值都应直接传递给智能指针.智能指针将确保delete在适当的时候自动为您调用.

顺便说一句,除非你是一个编写低级库(或学生学习如何做到这一点)的大师,否则你永远不应该调用new在C++中分配一个数组.标准库(以及Boost/TR1)提供了为您分配和管理数组的模板类.

总之,C++不使用垃圾收集器,但它确实有自己的自动内存管理形式.这两种方法之间存在细微差别,但这两种方法都可以自动释放内存,从而消除了大多数类型的内存泄漏.

这些概念的权威性演示由C++创建者Bjarne Stroustrup在回答问题时提供:我如何处理内存泄漏?

也可以看看:


Dre*_*all 8

关于operator new的陈述是完全正确的......但它过分简化了C++语义.

在C++中,可以在堆栈或堆上创建对象:

class Foo {};

int main() {
  Foo obj1;
  Foo* obj2 = new Foo();
  delete obj2;
}
Run Code Online (Sandbox Code Playgroud)

在上面的示例中,在堆栈上创建了obj1,并在堆上创建了obj2(使用new).在显式调用delete之前,不会销毁在堆上创建的对象.但是,堆栈上的对象在超出范围时会自动销毁(即在此示例中返回main()时).

这使得C++中的"资源获取初始化"成语(又称RAII)成为可能,它比基本垃圾收集功能强大得多.需要清理的资源(堆内存,套接字,文件,数据库连接等)通常放在基于堆栈的对象中,其析构函数负责清理.

相比之下,Java和C#不允许在堆栈上构造对象,并且不保证集合将会发生,也不保证终结器将运行(我不是C#的人,所以我可能会有点错误) .因此,当您在Java/C#中获得免费的堆内存管理时,您实际上会在这些语言中获得比在C++中更多的资源清理代码.