我仍然不相信在没有“构造”对象的情况下调用“析构函数”
I am still not convinced about a `destructor` being called without the object being `constructed`
案例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'
(,而不是错误,除非你试图为A
0定义一个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++。编译器必须对此发出诊断,并且允许完全不编译该诊断。如果编译器无论如何都编译它,那么该怎么处理它完全取决于编译器。在这种情况下,不破坏对象是明智的,但这需要额外的机制,这意味着正确的程序不需要额外的开销(程序需要检查内部标志是否构建了对象(。我不认为在编译时总是可以解决是否需要检查,因为这可能相当于停止问题。
- 什么时候调用组成单元对象的析构函数
- 使用基类指针创建对象时,缺少派生类析构函数
- 对具有动态分配的内存和析构函数的类对象的引用
- C++析构函数调用两次,堆栈分配的复合对象
- 如何从 Gtk::窗口调用派生对象的析构函数
- 为什么数组中对象的析构函数在被另一个对象替换时不被调用?
- 为什么为未删除的对象调用析构函数?
- 对象的构造函数和析构函数
- 循环中本地对象的析构函数是否保证在下一次迭代之前被调用?
- C++使用函数对象的线程,如何调用多个析构函数而不是构造函数?
- 从未调用shared_ptr对象的析构函数
- 是否可以在其析构函数中使用指向已销毁对象的指针?
- 使用私有析构函数删除动态分配的对象
- C++ std::线程调用方法,从对象原因到调用此类的析构函数
- 当我使用dynamic_cast并删除对象删除时,析构函数是如何工作的?
- C++ - 析构函数只是释放内存还是实际删除对象
- 受保护的析构函数禁用在堆栈上创建派生类的对象?
- 当 T 具有非平凡析构函数时,类类型 T 的对象是否可以常量初始化?
- 编译器是否在由 new 初始化的对象上调用隐式析构函数
- 受保护析构函数对象在堆vs堆栈上的分配