5

我无法弄清楚为什么在下一段代码中,定义的复制构造函数不打印......

#include <iostream>
using namespace std;
class B {
   static int count;
   int data; 
   int id;

   void print(const char* p)
   {
       cout <<p <<", "<<id <<", " << data << endl;
   }

   public:

   B(int d=0)
   {
      data=d; id=++count; print("B(int)");
   }
   B( const B& a)
   {
      data=a.data; id=++count; print("B(cost B&)");
   }
  ~B(){print("~B()");}

   operator bool(){ return (bool)data;}
   B operator+(int i){print("operator+"); return B(data+i);}
};


int B::count=0;

void main(){
   B b(42);
   B x=b+2;
   bool z=b+1;

   getchar();
}

我希望得到一个复制构造函数打印,B x=b+2但它没有显示。有任何想法吗?谢谢,


输出:

B(int), 1, 42
operator+, 1, 42
B(int), 2, 44
operator+, 1, 42
B(int), 3, 43
~B(), 3, 43

所以是返回值优化?

4

1 回答 1

1

我很快就把它放到了 GCC 中,并注意到了同样的行为。显然,编译器正在以它认为合适的方式改变代码的行为。

一:赋值不等于复制构造函数。我想因为它使用 '=' 它正在寻找 operator= 重载但没有找到它,然后选择使用其常规构造函数创建一个新的 B 对象,然后使用默认赋值将其复制到 x 中。这是有效的,因为它是一个简单的类。

我变了

B x=b+2;

B x(b+2);

试图强制它使用复制构造函数。但是我有同样的行为。然后我查看了 operator+ 的返回类型,发现它返回一个 B。(不是引用,但只要它遵守 C++11 之前的引用规则,它就可以被评估为引用)。因此,编译器再次以与上面相同的方式生成代码,因此我们没有使用复制构造函数。

如果你改变

B x(b+2);

B x(b);

编译器发现可以使用复制构造函数(也就是它能够生成对 b 的引用)。

我的猜测是,由于 operator+ 的返回类型,编译器正在生成代码。它可能与仅在 C++11 之前的非 const 引用如何作为左值处理有关。所以由于 operator+ 被调用,它不能从它创建一个 const 引用来传递给复制构造函数(因为 operator+ 的结果是一个左值)。因此,它使用常规构造函数和自动生成的赋值运算符来完成您请求的工作。

希望这可以帮助。

于 2013-07-03T15:30:07.583 回答