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

时间:2014-02-17 06:43:44

标签: c++ g++ language-lawyer

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


int main() {
    AAA a = 1;
    return 0;
}

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

在标准的第8.5节中:

  

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

     
      
  • 如果初始化是直接初始化,或者是复制初始化,那么cv-nonqualified版本的源   type与类的类相同,或者是类的派生类   目的地,建设者被考虑。适用的构造函数   列举(13.3.1.3),并通过过载选择最好的一个   决议(13.3)。如此选择的构造函数被调用以初始化   对象,初始化表达式或表达式列表作为其对象   参数(一个或多个)。如果没有构造函数适用,或者重载解析是   暧昧,初始化是不正确的。

  •   
  • 否则(即,对于剩余的复制初始化情况),可以从源转换的用户定义的转换序列   键入目标类型或(使用转换函数时)   按照13.3.1.4的描述列举其派生类别,   并且通过重载决策(13.3)选择最好的一个。如果   转换不能完成或模糊,初始化是   病态的。使用初始化程序调用所选的函数   表达作为其论点;如果函数是构造函数,则调用   初始化一个临时的cv-nonqualified版本的   目的地类型。临时是一个prvalue。通话的结果   (然后用于构造函数的临时情况)   直接初始化,根据上面的规则,对象就是   复制初始化的目的地。在某些情况下,   允许实现消除此中固有的复制   通过直接构造中间结果直接初始化   进入被初始化的对象;见12.2,12.8。

  •   

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

2 个答案:

答案 0 :(得分:3)

看起来像这个错误:g++ fails to call explicit constructors in the second step of copy initialization

  

g ++无法编译以下代码

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

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

复制初始化的第二步(见8.5 / 16 / 6/2)是一个   直接初始化,应考虑显式构造函数   作为候选人的职能。

答案 1 :(得分:1)

看起来永远不会调用复制构造函数。只调用构造函数。以下代码可以调用复制构造函数

AAA a = 1;
AAA ab = a;

不确定为什么G ++正在编译它。