为什么调用复制构造函数而不是转换构造函数?

Why is copy constructor called instead of conversion constructor?

提问人:Luchian Grigore 提问时间:6/27/2012 最后编辑:Luchian Grigore 更新时间:11/4/2019 访问量:4424

问:

所以基本上这段代码:

class A {
};
class B { 
   B (const B& b) {}
public: 
   B (){}
   B (const A& a) {} 
};

int main()
{
   A a;
   B b1(a);  //OK
   B b2 = a; //Error
}

仅生成 的错误。这个错误是B b2 = a

错误:“B::B(const B&)”是私有的

为什么除了直接转换构造函数之外,它还尝试调用复制构造函数?

从错误消息中可以清楚地看出,创建了一个临时文件,然后将其用于复制构造,但为什么呢?这在标准中的位置是什么?B

C++ 复制构造函数

评论

0赞 Eitan T 6/27/2012
你的问题是否与这个问题有关?:)
0赞 Eitan T 6/27/2012
因为我几分钟前已经回顾了这个问题:)
0赞 Steve Jessop 6/27/2012
因此,需要明确的是,你是在问编译器为什么要这样做(即你想要复制初始化定义的标准参考),还是在问标准为什么要这样做(即你想要该定义的动机)?
1赞 Luchian Grigore 6/27/2012
@SteveJessop我首先要求提供参考资料,但动机也很高兴知道(不会发布新问题,因为它可能会被删除)。
0赞 Luchian Grigore 6/27/2012
@SteveJessop公平。我认为杰西对阿尔斯回答的评论是一个可能的解释。

答:

14赞 Alok Save 6/27/2012 #1
B b2 = a;

这称为复制初始化

它执行以下操作:

  1. 使用 创建类型的对象。BaB (const A& a)
  2. 使用 将创建的临时对象复制到 。b2B (const B& b)
  3. 使用 销毁临时对象。~B()

您得到的错误不是在步骤 1 中,而是在步骤 2 中。

这在标准中的位置是什么?

C++03 8.5 初始化器
第 14 段:

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

— 否则(即,对于剩余的复制初始化情况),可以按 13.3.1.4 中所述枚举可以从源类型转换为目标类型或(当使用转换函数时)转换为其派生类的用户定义的转换序列,并通过重载解析 (13.3) 选择最佳转换序列。如果转换无法完成或不明确,则初始化格式不正确。使用初始值设定项表达式作为其参数调用所选函数;如果函数是构造函数,则调用将初始化目标类型的临时值。然后,根据上述规则,调用的结果(对于构造函数情况是临时的)用于直接初始化作为复制初始化目标的对象。在某些情况下,允许实现通过将中间结果直接构造到正在初始化的对象中来消除此直接初始化中固有的复制;见12.2、12.8。

评论

1赞 Luchian Grigore 6/27/2012
但是为什么不直接使用转换构造函数呢?
0赞 Alok Save 6/27/2012
@LuchianGrigore:确实如此。错误是在转换完成后,在复制构造期间。也可以省略对复制构造函数的调用,但这取决于编译器。此外,复制构造函数仍然需要可访问。
0赞 Luchian Grigore 6/27/2012
是的,我明白了(我知道无论是否被召唤,它们都必须可见)。但为什么不一步到位呢?为什么需要临时?B
0赞 Luchian Grigore 6/27/2012
好吧,我在这个问题中的措辞很糟糕。已编辑:)
1赞 Jesse Good 6/27/2012
@LuchianGrigore:我认为原因是为了更接近内置类型的语义。例如,这里发生了 2 件事。 转换为 ,然后将值赋值给 ,只有转换运算符不会模仿语义(我相信)。int i = 1.0;1.0inti