-2

由于我在 Java 方面获得了更多经验,并且我现在正在潜入 C++ 世界,所以我在 Java 中知道一些东西,但我不确定它是否像在 C++ 上一样工作。

实际上我得到了这个伪 C++ 代码:

unsigned long __stdcall MyFunction()
   {
    //Do some code that will take a while to complete...

       {
            MY_BIG_STRUCT mbStruct = {};
            mbStruct.a = "a";
            [...];
            UseMyStructData(&mbStruct);
        }

    //Do some code that will take a while to complete...

    return EXIT_SUCCESS;
}

所以我的问题是:在 JAVA 上使用括号内的那些代码块{}将标记为“释放”这些变量以 GC 释放它们,即使函数没有完成它的执行。那么,在 C++ 上,这以同样的方式工作吗?{}或者如果我没有块语句(如 if、while、switch 等),使用它是无用的?

此致,

阿方索·拉格。

4

4 回答 4

2

非托管 C++ 中没有 GC。mbStruct 的析构函数将在}括号末尾调用,但是因为它是堆栈上的变量(而不是堆上的new)。创建一个作用域,导致在{ }结束作用域括号处调用析构函数。即使从函数中抛出异常,也保证析构函数运行。

此外,C++ 采用“确定性破坏”,这意味着您可以保证析构函数将同步运行(在关闭时}),而不是在具有 GC 的系统中,对象由 GC 内存管理器自行处理。

于 2013-10-13T20:37:59.190 回答
1

在堆栈上分配的自动变量将被释放。这与 Java 中的垃圾收集器不同,因为它是自动堆栈分配,而不是堆分配。使用方面,它对你来说看起来是一样的。

如果你从堆中分配一些东西(使用new/ malloc) - 你必须自己取消分配(使用delete/ free)。为此使用unique_ptrshared_ptr

于 2013-10-13T20:39:10.327 回答
1

C++ 中没有 GC。但是,垃圾收集器只处理动态分配的内存。那是与newor malloc()。自动变量在其范围退出时被销毁。mbStruct是一个自动变量,所以它会在超出范围时被销毁。

此外,您不需要显式{ }范围,除非您想要细粒度的控制。另请注意,范围甚至在关闭之前就结束了}。例如:

void foo()
{
    SomeClass someObj;
    if (some_condition) {
        return;
    }
}

someObj即使some_condition是 true 并且return被执行,也会被销毁;离开作用域与结束作用域具有相同的效果。

您应该注意不要保留指向超出范围的变量的指针(或引用)。例如,这会爆炸:

void foo()
{
    SomeClass* someObj_ptr;

    {
        SomeClass someObj;
        someObj_ptr = &someObj;
    }
    someObj_ptr->function(); // Mistake: someObj no longer exists.
}

内部作用域结束后,someObj已销毁但someObj_ptr仍引用它。调用function()它(假设SomeClass有这样的成员函数)是一个错误。请注意,编译器无法捕获该错误。您必须意识到这一点,并且永远不要保留对超出范围的变量的指针或引用。与 Java 不同,在 C++ 中,变量不被引用计数,并且如果有对它们的引用,则不会保持活动状态。如果一个变量超出范围,它就消失了,不管其他变量是否仍然引用它们。

于 2013-10-13T20:40:21.780 回答
0

在 C++ 中的工作方式相同。您的MY_BIG_STRUCT遗嘱将在区块结束时被释放。

于 2013-10-13T20:38:45.053 回答