为什么复制构造函数在通过const引用传递临时时被调用?

时间:2011-01-19 09:11:57

标签: c++ gcc pass-by-reference copy-constructor

我将一个未命名的临时对象传递给使用const ref参数定义的函数。该类的副本是私有的,我收到编译错误。我不明白为什么在这种情况下调用复制构造函数。

class A {
public:
  A(int i) {}
private:
  A(const A&) {}
};

void f(const A& a)
{
}

int main()
{
  f(A(1)); // <-- error here: 'A::A(const A&)' is private
}

正如预期的那样,当我将主要内容更改为:

A a(1);
f(a);

它有效。

编辑:编译器是gcc 4.1.2

3 个答案:

答案 0 :(得分:20)

表达式A(1) rvalue 5.2.3 [expr.type.conv]。

在使用 rvalue 表达式初始化const引用(函数参数)时,编译器可能创建临时值并复制该值表达式临时并绑定对该临时的引用。 8.5.3 [dcl.init.ref] / 5.

  

[...]无论副本是否真正完成,用于制作副本的构造函数都应该是可调用的。

请注意,此行为是由于下一版本的C ++发生了变化。在新标准中,从类 prvalue 初始化的const引用必须直接绑定到引用对象;在这种情况下,不允许创建临时文件,并且不使用或不需要复制构造函数。

答案 1 :(得分:18)

您可以在Copy Constructor Needed with temp object中找到问题的答案,或直接转到http://gcc.gnu.org/bugs/#cxx%5Frvalbind

  

C ++标准说是暂时的   应该在这里创建对象   上下文及其内容充满了   我们正在尝试的对象的副本   绑定到引用;它还说   可以省略临时副本,   但是语义约束(例如。   复制构造函数的可访问性   仍然需要检查。

     

有关详细信息,您可以   请参考以下段落   C ++标准:[dcl.init.ref] / 5,   子弹2,子弹1和   [class.temporary] / 2。

     

从GCC 4.3.0开始,不再是GCC   给出了这种情况的错误。这个   变化是基于的意图   C ++语言委员会。作为   2010-05-28,最终提出草案   C ++ 0x标准允许这样做   代码没有错误。

答案 2 :(得分:0)

因为a(1)调用构造函数A(int i),然后在调用void f(const A&amp;)时调用A(const A&amp;)。

使A(int i)构造函数显式,你不应该面对这个错误。

编辑:我想我误解了这个问题。我可能会删除它。