gpt4 book ai didi

c++ - 编译器对析构函数省略的自由度是多少?

转载 作者:IT老高 更新时间:2023-10-28 21:34:06 26 4
gpt4 key购买 nike

众所周知,在某些情况下,编译器可能会忽略对复制构造函数的调用。但是,标准明确指出,编译器只能自由更改运行时行为(调用或不调用复制构造函数),但执行翻译时就像调用复制构造函数一样。特别是,编译器会检查是否有有效的复制构造函数可以调用。

我遇到了这样一种情况,即可能会省略析构函数调用,但编译器在是否需要存在有效析构函数方面存在差异。

这是一个完整的示例,展示了此问题如何发生以及编译器的行为有何不同。

template <typename T>
struct A {
~A() { (void) sizeof(T); }
};

struct B; // defined elsewhere.

struct C {
A<B> x, y;
~C(); // defined in a TU where B is complete.
};

int main() {
C c;
}

编译时main()编译器生成 C的默认构造函数。此构造函数默认首先初始化 x然后 y .如果在 y 期间抛出异常 build ,然后x必须销毁。生成的代码如下所示:

new ((void*) &this->x) A<B>;   // default initializes this->x.
try {
new ((void*) &this->y) A<B>; // default initializes this->y.
}
catch (...) {
(this->x).~A<B>(); // destroys this->x.
throw;
}

知道 A<B>的默认构造函数是微不足道的(并且不会抛出),在 as-if 规则下,编译器可能会将代码简化为:

new ((void*) &this->x) A<B>;   // default initializes this->x.
new ((void*) &this->y) A<B>; // default initializes this->y.

因此,无需调用 ~A<B>() . (实际上,编译器甚至可以删除上面的两个初始化,因为 A<B> 的构造函数是微不足道的,但这对于本次讨论并不重要。)

问题是:即使对析构函数的调用可能被省略,编译器是否应该验证有效的析构函数是否可用?我在标准中找不到任何可以澄清问题的内容。谁能提供相关的报价?

如果编译器决定不翻译 ~A<B>() (就像 gcc 和 Visual Studio 一样)然后编译成功。

但是,如果编译器决定翻译 ~A<B>()无论如何(就像 clang 和 icc 一样),然后它会引发一个错误,因为这里 B是不完整的类型,无法取其大小。

最佳答案

我不认为这是标准规定的。如果 ~A<B>被实例化然后它是格式错误的并且需要诊断。正如你所说,如果构建 y抛出,然后 x必须销毁。

但是,构造 y永远不能抛出,因此可以说永远不会要求析构函数的定义存在(15.2/2、14.7.1/3)。

关于c++ - 编译器对析构函数省略的自由度是多少?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23184712/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com