在复制初始化中,是复制构造函数的显式还是隐式调用?

goo*_*era 8 c++ g++ language-lawyer

class AAA {
public:
    explicit AAA(const AAA&) {}
    AAA(int) {}
};


int main() {
    AAA a = 1;
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

在上面的代码中,据我所知,虽然在大多数情况下已经省略,但仍然需要在语义上调用复制构造函数.我的问题是,呼叫是明确的还是隐含的?很长一段时间,我在脑海中得出结论,调用AAA::AAA(int)是隐式的,但是对复制构造函数的调用不是.今天我偶然得到了g ++来编译上面的代码并报告错误.(VC12编译正常.)

在标准的第8.5节中:

如果目标类型是(可能是cv限定的)类类型:

  • 如果初始化是直接初始化,或者它是复制初始化,其中源类型的cv-nonqualified版本与目标类相同的类或派生类,则考虑构造函数.列举了适用的构造函数(13.3.1.3),并通过重载解析(13.3)选择最佳构造函数.调用所选的构造函数来初始化对象,初始化表达式或表达式列表作为其参数.如果没有构造函数适用,或者重载决策是不明确的,则初始化是错误的.

  • 否则(即,对于剩余的复制初始化情况),可以如13.3中所述枚举可以从源类型转换为目的地类型或(当使用转换函数时)到其派生类的用户定义的转换序列. 1.4,通过重载决策(13.3)选择最好的一个.如果转换不能完成或不明确,则初始化是错误的.选择的函数以初始化表达式作为参数调用; 如果函数是构造函数,则调用初始化目标类型的cv-nonqualified版本的临时函数.临时是一个prvalue.然后,根据上面的规则,调用的结果(对于构造函数的情况是临时的)用于 直接初始化作为复制初始化目标的对象.在某些情况下,允许实现通过将中间结果直接构造到正在初始化的对象中来消除此直接初始化中固有的复制; 见12.2,12.8.

direct-initialize上面引号中的粗体表示对复制构造函数的调用是明确的,对吧?是g ++错误还是我对标准的解释错了?

小智 3

看起来像这个错误:g++ 在复制初始化的第二步中无法调用显式构造函数

g++ 无法编译以下代码

struct X
{
    X(int) {}
    explicit X(X const &) {}
};

int main()
{
    X x = 1; // error: no matching function for call to 'X::X(X)'
}
Run Code Online (Sandbox Code Playgroud)

复制初始化(参见 8.5/16/6/2)的第二步是直接初始化,其中显式构造函数应被视为候选函数。