Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/135.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ C++;统一初始化是异常安全的标准保证?_C++_Exception_Gcc_C++17_Uniform Initialization - Fatal编程技术网

C++ C++;统一初始化是异常安全的标准保证?

C++ C++;统一初始化是异常安全的标准保证?,c++,exception,gcc,c++17,uniform-initialization,C++,Exception,Gcc,C++17,Uniform Initialization,而gcc输出: A ~A 这似乎是GCC的一个严重缺陷 有关参考,请参阅和 我只是想知道: < C++ >标准是否保证了统一的初始化是异常安全的?< /强> ,看起来是这样的: 在所有地方的§6.6/2跳转语句[stmt.Jump]中发现了奇怪的内容(N4618): 从作用域退出时(无论如何完成),对象将自动 在该范围内建造的储存期限(3.7.3)如下: 按与建筑相反的顺序被摧毁。[注:适用于 临时表,见12.2.-结束注释]从循环中转移,从循环中转移 块,或通过自动存储返回初始化变量 持续

gcc
输出:

A
~A
这似乎是GCC的一个严重缺陷

有关参考,请参阅和

我只是想知道:

< C++ >标准是否保证了统一的初始化是异常安全的?< /强>

,看起来是这样的:

在所有地方的§6.6/2跳转语句[stmt.Jump]中发现了奇怪的内容(N4618):

从作用域退出时(无论如何完成),对象将自动 在该范围内建造的储存期限(3.7.3)如下: 按与建筑相反的顺序被摧毁。[注:适用于 临时表,见12.2.-结束注释]从循环中转移,从循环中转移 块,或通过自动存储返回初始化变量 持续时间包括使用自动存储销毁对象 在传输点处于范围内但不在传输点的持续时间 这一点转移到。(参见第6.7节,了解向区块的转移)。[注: 但是,可以终止程序(通过调用
std::exit()
std::abort()
(例如,18.5)而不销毁类对象 具有自动存储持续时间。-结束注释]

我认为这里的重点是“(无论完成程度如何)”部分。这包括一个异常(但不包括导致
std::terminate
)的事件)


编辑 我认为更好的参考是§15.2/3构造函数和析构函数[除.ctor外](emphasis我的):

如果初始化或销毁除 委托构造函数被异常(析构函数)终止 为每个对象的直接子对象调用,并为 完整对象,虚拟基类子对象,其初始化 已完成(8.6),且其析构函数尚未开始执行, 除了在销毁的情况下,一个 工会式的阶级不会被摧毁。子对象在中被销毁 其施工完成的相反顺序。这样的 销毁在进入 构造函数或析构函数的函数try块(如果有)

这将包括聚合初始化(我今天学到的可以称为非真空初始化)

…对于具有构造函数的对象,我们可以引用§12.6.2/12[class.base.init](emphasismine):

在非委托构造函数中,每个构造函数的析构函数 可能会调用类类型的构造子对象(12.4)。[ 注意:此规定确保可以调用析构函数 在引发异常时完全构造的子对象(15.2)。 -[完注]


什么版本的GCC展示了这一点?@einpoklum all。我不认为异常安全是这里的一个问题。除非1)通过exit()立即退出应用程序,2)未定义的行为,--如果对象在自动作用域中构造,则当执行离开其作用域时,必须将其销毁。这是C++的基础。这是一个编译器错误。首先,我认为这可能是一些愚蠢的优化,因为静态分析发现程序会立即在catch-all处理程序上退出。但不,这是一个编译器错误。所以你有一个博客说这是一个bug,还有一个gcc bug报告说并确认它是一个bug。。。但是你有一个问题问它是不是一个bug?现在我在脑子里回顾我写的所有程序,这些程序可能会在未捕获的异常和失败的断言上危及系统…@YSC:好吧,失败的断言不应该使系统Jeapordi化。如果一个断言因为这个错误而失败,并且一个关键系统被关闭并重新启动,而不是提供随机行为,那么我认为断言确实执行了它设计要执行的任务。这正是你将它放在那里的原因-在面对可怕的错误时保护系统完整性和数据一致性。@ChristianHackl我担心“[注:但是,程序可以终止(例如通过调用std::exit()或std::abort()(18.5)),而不会破坏具有自动存储持续时间的类对象。-结束说明]”@YSC:Ah,我想我误解了你的评论。然而,在这种情况下,失败的断言应该更不用担心,不是吗?事实上,这正是您使用
断言
退出
中止
的原因;您不希望执行更多的代码,因为您已经检测到一个bug或某种紧急情况,其中包括析构函数中的代码。我的观点是:在C++的某些情况下,不执行本地对象的析构函数是正确的和理想的,而是立即退出。当然,这个可怕的GCC错误不是其中之一。@ChristianHackl是的,我同意。我只是从来没有想过。
A
~A
A