由于我有更多的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等等),使用{}
是无用的?
致以最诚挚的问候,
Afonso Lage。
答案 0 :(得分:2)
非托管C ++中没有GC。 mbStruct的析构函数将在}
括号的末尾调用,但是因为它是堆栈上的变量(而不是在new
的堆上)。
{
}
创建一个范围,使得在结束范围括号中调用析构函数。即使从函数中抛出异常,析构函数也能保证运行。
此外,C ++采用“确定性破坏”,这意味着您可以保证析构函数将同步运行(在结束}
),而不是具有GC的系统,其中对象在GC内存管理器的自由裁量权。
答案 1 :(得分:1)
将在堆栈上分配的自动变量被释放。这与Java中的垃圾收集器不同,因为它是自动堆栈分配,而不是堆分配。在使用方面,它看起来与你一样。
如果您从堆中分配了某些内容(使用new
/ malloc
) - 您必须自行取消分配(使用delete
/ free
)。请使用unique_ptr或shared_ptr。
答案 2 :(得分:1)
C ++中没有GC。但是,垃圾收集器只处理动态分配的内存。这是new
或malloc()
。当范围退出时,自动变量将被销毁。 mbStruct
是一个自动变量,因此当它超出范围时会被销毁。
此外,除非您需要精细控制,否则不需要显式{ }
范围。另请注意,范围在结束}
之前结束。例如:
void foo()
{
SomeClass someObj;
if (some_condition) {
return;
}
}
即使someObj
为真且some_condition
已执行, 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 ++中,变量不是引用计数,如果有引用则不会保持活动状态。如果变量超出范围,它就会消失,无论其他变量是否仍然引用它们。
答案 3 :(得分:0)
在C ++中以相同的方式工作。您的MY_BIG_STRUCT
将在阻止结束时发布。