我仍然不相信在没有“构造”对象的情况下调用“析构函数”

I am still not convinced about a `destructor` being called without the object being `constructed`

本文关键字:析构函数 对象 情况下 调用 构造 不相信      更新时间:2023-10-16

案例1

这是基于我昨天发布的另一个问题,我接受了,尽管很不情愿,但可以用以下代码总结:

{
    ...
    goto Label;
    A a;
    ...
    Label:DoSomething();
}

其中CCD_ 1是具有定义的CCD_ 2和默认CCD_。DoSomething()不使用a。根据我的理解(我仍在为C++的基本构造而挣扎(,A的析构函数在这种情况下不会被调用,因为对象a甚至没有被构造。

请注意,VS2008编译器会给你一个警告(C4533 : initialization of 'a' is skipped by 'goto Label'(,而不是错误,除非你试图为A0定义一个destructor,当编译器神秘地将警告更改为错误(C2362 : initialization of 'a' is skipped by 'goto Label'(时,就好像阻止某人调查这个问题,顺便说一句,这让我想起了自然界中的量子现象。

情况2

这是constructor抛出异常的正常情况,在这种情况下,destructor不会被调用,如这里和这里所讨论的。

因此

Case1中,constructor没有被调用,但destructor被调用以销毁未创建的东西,这对我来说似乎很奇怪。在Case2,构造函数被调用,抛出异常,destructor没有被调用。

我认为这两个例子值得进一步澄清。

编辑

Case2中,编译器可能会使用标志来避免破坏由于抛出而未构造的对象。为什么在Case1中不能使用这些相同的标志来识别由于goto而没有构建的对象?

在C++中,跨变量初始化(构造函数调用(的goto正是因为这个原因而被禁止的:goto跳过构造函数调用。在goto和对DoSomething的调用之后,变量a将超出作用域,因此将在a上调用析构函数,因为goto跳过了构造函数调用,所以尚未构造该函数。

VS2008在这里是宽松的,当自动生成的析构函数(可能在POD上(没有效果时,它允许违反标准。

实际上情况1是无效的C++。编译器必须对此发出诊断,并且允许完全不编译该诊断。如果编译器无论如何都编译它,那么该怎么处理它完全取决于编译器。在这种情况下,不破坏对象是明智的,但这需要额外的机制,这意味着正确的程序不需要额外的开销(程序需要检查内部标志是否构建了对象(。我不认为在编译时总是可以解决是否需要检查,因为这可能相当于停止问题。