为什么 C++ 中的强制 RVO 需要 public 析构函数?

Why is public destructor necessary for mandatory RVO in C++?

请考虑下面的简单示例,其中函数 bar return 是 class A 的对象,具有私有析构函数,并且强制性 return 必须进行价值优化 (RVO):

class A { ~A() = default; };
A bar() { return {}; }

代码被 Clang 接受,但被 GCC 拒绝并出现错误:

error: 'constexpr A::~A()' is private within this context
    2 | A bar() { return {}; }
      |                   ^

https://gcc.godbolt.org/z/q6c33absK

哪一位编译器就在这里?

这是CWG 2426。在此上下文中可能会调用析构函数,因为即使在 return A 对象初始化之后,该函数仍有可能无法成功完成:在 return 语句期间创建的任何临时对象和范围内的自动局部变量必须被销毁,如果销毁抛出,那么作为堆栈展开的一部分,A 对象被销毁。编译器应该 要求此时可以访问析构函数。

注1:函数最外层作用域的局部变量的析构函数抛出的异常可以被函数try块捕获。

注2:在return对象销毁后,允许handler执行另一个return语句。标准中有一个这样的例子。

有很多像问题中这样的简单情况,可以很容易地证明永远不会使用析构函数,但是使用了代码。

虽然决定这个问题可能会变得任意复杂,这是标准化的祸根。将它留在实施者手中将因此分裂语言,创建不兼容的子方言,因为他们会付出不同的努力来决定(不同的)极端情况。

但这还不是结束,因为解决问题意味着解决停机问题,因此 甚至不是难以处理的,而是不可判定的.

因此,像 CWG 2426 那样回避它不仅是为了理智(指定所有细节变得非常笨重),而且是唯一的选择,而不是在口述任意数量的任意选择后随意画一条线简单的案例。