【问题标题】:Why is copy constructor called instead of conversion constructor?为什么调用复制构造函数而不是转换构造函数?
【发布时间】:2012-06-28 15:23:15
【问题描述】:

所以基本上这段代码:

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,然后将其用于复制构造,但为什么呢?这在标准中的什么地方?

【问题讨论】:

  • 您的问题是否与this one 相关? :)
  • 因为我在几分钟前已经复习过这个问题 :)
  • 所以要清楚,您是在问为什么 compiler 会这样做(即您想要复制初始化定义的标准参考),还是在问为什么标准正在这样做(即你想要那个定义的动机)?
  • @SteveJessop 我首先要求提供参考,但动机也很高兴知道(不会发布新问题,因为它可能会被删除)。
  • @SteveJessop 公平。我认为 Jesse 对 Als 回答的评论是一个可能的解释。

标签: c++ copy-constructor


【解决方案1】:
B b2 = a;

这称为 Copy Initialization

它执行以下操作:

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

你得到的错误不是在第 1 步,而是在第 2 步。

这在标准中的什么地方?

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

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

【讨论】:

  • 但是为什么不直接使用转换构造函数呢?
  • @LuchianGrigore:确实如此。错误是转换完成之后,在复制构造期间。对复制构造函数的调用也可以省略,但这取决于编译器。此外,仍然需要可访问复制构造函数。
  • 是的,我明白了(而且我知道无论是否调用它们,它们都必须可见)。但是为什么不一步一步完成呢?为什么需要临时的B
  • 好的,我在问题中措辞不佳。已编辑:)
  • @LuchianGrigore:我认为原因是更接近内置类型的语义。例如,int i = 1.0;:这里发生了 2 件事。 1.0 被转换为int 并且然后将该值分配给i,只有一个转换运算符不会模仿语义(我相信)。
猜你喜欢
  • 2017-09-04
  • 2015-06-10
  • 1970-01-01
  • 2013-04-25
  • 2012-04-29
  • 1970-01-01
  • 2012-02-28
  • 1970-01-01
相关资源
最近更新 更多