java - C/C++ 与 Java 中的垃圾收集

标签 java c++

C/C++ 中没有自动垃圾收集。

假设我用 C/C++ 编写了一个简单的程序并创建了一个对象。 假设恰好有10个或极其有限的地址可供分配。

我有一个运行 100 次的 for 循环,每次循环运行时都会在其中创建一个对象。

在Java中,因为有自动垃圾回收机制,每次执行完一个循环后,每次都会自动清除对象的地址。

粗略示例:

for(int i = 0; i < 100; i++)
{
   Object o = new Object;
}

在 C/C++ 中,我们必须手动删除 for 循环中的对象地址。我们是否每次都必须重新启动才能正确删除 C++ 中的对象引用?


对于那些说在 C++ 中多次删除一个对象没有问题的人。来自维基百科:

When an object is deleted more than once, or when the programmer attempts to release a pointer to an object not allocated from the free store, catastrophic failure of the dynamic memory management system can result. The result of such actions can include heap corruption, premature destruction of a different (and newly created) object which happens to occupy the same location in memory as the multiply deleted object, and other forms of undefined behavior.

链接:Manual Memory Management

所以有风险?

最佳答案

C++ 没有(内置的)垃圾收集,但这并不意味着您应该让动态分配的内存永远保持分配状态。您可以并且应该释放它。最基本的方法是在您不再需要时手动释放您的对象引用(或指针,因为这是 C++):

for(int i = 0; i < 100; i++)
{
   // Dynamically allocate an object
   Object* o = new Object();

   // do something with object

   // Release object memory (and call object destructor, if there is one)
   delete o;
}

但是,如果您在堆栈上分配对象,当它超出范围时,它总是会自动释放,您不必等待垃圾回收发生 - 它总是立即释放:

for(int i = 0; i < 100; i++)
{
   // Create a new object on the stack
   Object o = Object(); // Note we're not using the new keyword here.

   // Do something with object

   // Object gets automatically deallocated, or more accurately, in this specific
   // case (a loop), the compiler will optimize things, so object's destructor
   // will get called, but the object's stack memory will be reused.
}

C++ 堆栈值的这种行为(当它们超出范围时自动销毁),被笨拙地称为 RAII(资源获取即初始化)允许 Java 做不到的非常好的事情。其中之一是智能指针,它允许动态分配的对象像堆栈对象一样自动释放,如果需要,您可以使用复杂的智能指针来实现您自己的垃圾收集版本。

RAII 的另一个优点是在 C++ 中很少需要 finally block :引用应立即释放的资源的局部变量通常分配在堆栈上,因此会自动释放。这里不需要 finally block 。

实际上,当使用 C++ 编程时,您通常会将局部变量放在堆栈上(并且无需费力即可获得 RAII 的所有优点),除非您需要让它们存活更长时间(例如,您需要创建一个对象并存储对它的引用,当您离开创建该对象的函数时该引用仍然存在)。在那种情况下,您可以直接使用指针,但如果您不想处理手动删除指针以及它可能导致的所有问题,您通常会使用智能指针。智能指针是在堆栈上分配的对象,它包装了一个“哑”(即常规)指针,并在调用其析构函数时删除该指针。更高级版本的智能指针可以实现引用计数(因此只有当所有 引用它的智能指针超出范围时才会释放指向的对象)甚至垃圾收集。标准库自带两个智能指针:auto_ptrsmart_ptr(后者是引用计数,但有些旧的编译器可能不支持)。

关于java - C/C++ 与 Java 中的垃圾收集,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5842737/

相关文章:

java - 使用同一个类 Spring 多个 @ConfigurationProperties

java - Spring-boot 安全记住我 token 不起作用

java - 数组未正确打印所有答案

C++:使用 mem_fn 和 bind1st 创建函数对象

c++ - C++ 中的多线程应用程序和 OpenCV?

java - 优化对象列表的fasterxml ObjectMapper

java - 在 Java 应用程序中显示文件(图像)

c++ - 智能指针与拥有原始指针

c++ - Bison :存储自定义类

c++ - 如何在没有 Xlib 的情况下配置 QT5