标准C ++中的垃圾收集是否自动?

据我所知,在标准C ++中,无论何时使用new运算符,都必须在某个时刻使用delete运算符来防止内存泄漏。 这是因为在C ++中没有垃圾收集。 在.NET中,垃圾收集是自动的,所以不需要担心内存管理。 我的理解是否正确? 谢谢。


长时间的答案是,每次调用new ,在某个地方,不知何故,必须调用delete ,或者其他一些deallocation函数(取决于内存分配器等)

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

  • C ++有垃圾收集,采用Hans-Boehm Garbage Collector的形式。 也可能有其他垃圾收集库。
  • 您可以使用智能指针,使用RAII(如果指针允许共享访问,则使用引用计数)来确定何时删除对象。 一个好的智能指针库是Boost的智能指针。 绝大多数情况下的智能指针可以取代原始指针。
  • 一些应用程序框架(如Qt)构建对象树,以便框架的堆分配对象具有父子关系。 因此,所有需要的是在对象上调用delete ,并且其所有子对象也将自动delete
  • 如果您不想使用这些技术中的任何一种,为了防止内存泄漏,您可以尝试使用内存检查工具。 Valgrind特别好,但它只适用于Linux

    至于.NET,是的,使用gcnew分配意味着内存被.NET跟踪,所以没有泄漏。 但是,其他资源,如文件句柄等不受GC管理。


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

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

    class Foo {};
    
    int main() {
      Foo obj1;
      Foo* obj2 = new Foo();
      delete obj2;
    }
    

    在上面的例子中,在堆栈上创建obj1,并在堆上创建obj2(使用new)。 在堆上创建的对象不会被销毁,除非明确调用它们。 但是,堆栈中的对象在超出作用域时会自动销毁(即,在此示例中,当main()返回时)。

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

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


    在惯用的高级C ++中, 你永远不会调用delete

    C ++没有一个标准的垃圾回收器,它的工作原理与C#中的相同,因此,从根本上讲, newdelete需要配对。 但是,C ++中有一些机制完全消除了用现代风格编写的代码的显式使用delete

    首先要注意的事情是,在C ++中使用new更频繁地比你使用new的C#。 这是因为在C#中,每当创建结构,类或数组的实例时都使用new ,但在C ++中,只有在需要动态管理数据元素时才使用new 。 C ++中的大多数数据不需要动态管理,因此可以在不使用new情况下创建。 [换句话说,C#中的new与C ++有不同的含义。 在C ++中,它具体指示动态分配,而在C#中则用于任何构造。]

    其次,只要你在C ++中调用new ,返回值应该直接交给一个智能指针。 智能指针将确保在适当的时候自动为您调用delete

    顺便说一下,除非你是编写低级库的专家(或者学习如何做这件事的学生),否则你绝不应该用new来调用C ++中的数组。 标准库(以及Boost / TR1)提供了为您分配和管理阵列的模板类。

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

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

    也可以看看:

  • 动态内存管理参考 - 智能指针
  • 容器库参考 - 数组
  • 链接地址: http://www.djcxy.com/p/78499.html

    上一篇: Is garbage collection automatic in standard C++?

    下一篇: Malloc vs new