class A
{
 public:
  A(const int n_);
  A(const A& that_);
  A& operator=(const A& that_);
};

A::A(const int n_)
{ cout << "A::A(int), n_=" << n_ << endl; }

A::A(const A& that_)    // This is line 21
{ cout << "A::A(const A&)" << endl; }

A& A::operator=(const A& that_)
{ cout << "A::operator=(const A&)" << endl; }

int foo(const A& a_)
{ return 20; }

int main()
{
  A a(foo(A(10)));    // This is line 38
  return 0;
}

执行此代码给O / P:

  

A :: A(INT),N_ = 10,点击   A :: A(INT),N_ = 20结果

显然拷贝构造函数永远不会被调用。

class A
{
 public:
  A(const int n_);
  A& operator=(const A& that_);
 private:
  A(const A& that_);
};

但是,如果我们把它变成私有,出现此编译错误:

  

Test.cpp的:在函数“诠释主()”:结果   TEST.CPP:21:错误:“A :: A(const的A&)”是私有的结果   TEST.CPP:38:错误:这个上下文中

为什么编译器抱怨时,它实际上并不使用拷贝构造函数?结果 我使用gcc版本4.1.2 20070925(红帽4.1.2-33)

有帮助吗?

解决方案

核心缺陷391 解释该问题。

基本上,当前的C ++标准要求一个拷贝构造使临时类型的一个const参考时是可用的。

这要求将C ++ 0x中被移除。

后面需要复制构造逻辑来源于此情况下:

C f();
const C& r = f(); // a copy is generated for r to refer to

其他提示

在2003标准,在§12.2/ 1,规定:

  

即使当创建的   临时对象被避免(12.8),   所有的语义限制必须是   推崇为如果临时对象   已创建。 [实施例:即使   拷贝构造函数不叫,一切   语义的限制,例如   可访问性(第11条),应   满意。 ]

有围绕类似的例子。从我所收集,编译器可以自由生成的临时或优化他们离开。

据我看你是不是使用拷贝构造函数的任何地方。在声明中foo(A(10))正在创建A类的临时对象,并把它当作一个const引用到foo中。 foo的返回其在对象a的构建中使用的整数。因此,我没有看到那里的拷贝构造抵达该处参与和NRVO如何进入画面。另外,我通过使复制构造私人和它在VS2008编译细编译下面的代码。

using namespace std;

class A
{
 public:
  A(const int n_);
 private:
  A(const A& that_);
  A& operator=(const A& that_);
};

A::A(const int n_)
{ cout << "A::A(int), n_=" << n_ << endl; }

A::A(const A& that_)    // This is line 21
{ cout << "A::A(const A&)" << endl; }

A& A::operator=(const A& that_)
{ 
    cout << "A::operator=(const A&)" << endl; 
    return *this;
}

int foo(const A& a_)
{ return 20; }


int main(int argc,char *argv[])
{
   A a(foo(A(10)));    // This is line 38
  return 0;

}   

又一个备注:使用临时工作时,编译器做不同的事情。所以它不是关于拷贝构造函数,它是关于中间暂时的。

A original(10);
foo( original ); // does compile
foo( A(10) ); // doesn't compile - needs a copy constructor

在表达式:

A a(foo(A(10)));

子表达式A(10)的结果是一个右值类型A的。 (5.2.3 [expr.type.conv])

当初始化从右值编译器可以从右值创建临时和结合,为所述参考const引用。即使选择不,拷贝构造函数必须是可访问。 (8.5.3 [decl.init.ref])这将不会是这种情况,如果有基准正在从一个参考兼容 左值其中直接结合的任务初始化。

foo需要通过引用而不是值及其参数,也没有规定对自变量初始化本身。

拷贝

foo返回int,所以没有一个A的副本在这里。

a是直接从由富返回的INT初始化,所以没有A这里的副本。

在拷贝构造没有被使用,但为了使代码编译拷贝构造需要是可访问的。

编辑:科莫C ++编译器报告如下:

Comeau C/C++ 4.3.10.1 (Oct  6 2008 11:28:09) for ONLINE_EVALUATION_BETA2
Copyright 1988-2008 Comeau Computing.  All rights reserved.
MODE:strict errors C++ noC++0x_extensions

"ComeauTest.c", line 38: error: "A::A(const A &)" (declared at line 17), required
          for copy that was eliminated, is inaccessible
    A a(foo(A(10)));    // This is line 38
            ^

1 error detected in the compilation of "ComeauTest.c".

请注意,如果C ++ 0X扩展被启用,它编译在科莫C ++编译器的罚款。

在一般情况下,你不应该对是否以及何时拷贝构造函数被调用去担心。 C ++标准是相当宽松的有关何时拷贝构造函数调用将被删除,或为此事增加。如果您的类逻辑需要它,它提供了(不要忘记析构函数和赋值运算符)是合理的规则。

致电时:

foo( A(10) );

时,该呼叫的生命周期中被创建的临时对象。复制构造被用来填充数据。临时对象被调用的执行之后被去除。

致电时:

{ 
  A original(10);
  foo( original ); 
}

在原始正在离开块后丢弃。它可以安全地被用作一个参数。

有关最佳速度,通过引用传递的对象,使用将被编译器在优化过程被丢弃临时变量。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top