对于调用结果的复制初始化序列,它是否被认为是 GCC 和 Clang 的错误?

jac*_*k X 3 c++ language-lawyer c++20

请看这个例子

#include <iostream>
struct A{
    A(){
        std::cout<<"A constructed\n";
    }
    ~A(){
        std::cout<<"A destroyed\n";
    }
};
struct B{
    B(int){
        std::cout<<"B constructed\n";
    }
    ~B(){
        std::cout<<"B destroyed\n";
    }
};
struct C{
    C(){
       std::cout<<"C constructed\n"; 
    }
    ~C(){
        std::cout<<"C destroyed\n";
    }
    bool operator==(B const&){
        return true;
    }
};
struct D{
    D(bool){
        std::cout<<"D constructed\n";
    }
};
bool fun(){
    A a;
    C c;
    return c==0;
}
int main(){
    D d = fun();
}
Run Code Online (Sandbox Code Playgroud)

上面例子的输出在 GCC 和 Clang 中都是相同的,它们是

A constructed
C constructed
B constructed
B destroyed
C destroyed
A destroyed
D constructed
Run Code Online (Sandbox Code Playgroud)

这意味着调用结果的复制初始化在该函数的局部或临时变量的所有销毁之后进行排序。它与以下规则相矛盾,即
[stmt.return#3]

调用的结果中的复制初始化之前测序在由return语句,这反过来,是局部变量的破坏之前测序的操作建立完整的表达年底的临时的破坏([语句.jump]) 包含 return 语句的块。

根据规则,输出应该是

A constructed
C constructed
B constructed
D constructed
B destroyed
C destroyed
A destroyed
Run Code Online (Sandbox Code Playgroud)

是 GCC 和 Clang 的错误吗?

Sam*_*hik 5

相关函数的返回值是 a bool。这就是返回的内容。

您记录的输出没有显示bool返回值的复制初始化何时排序的证据,在其他任何事情之前或之后。

也恰好是一旦bool返回值,调用者就使用它来构造 的新实例D。但这bool与函数调用返回值的复制初始化语义完全无关。