C++ Copy Constructor Oddity

Alo*_*aky 5 c++ copy-constructor

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

#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();
}
Run Code Online (Sandbox Code Playgroud)

我希望得到一个复制构造函数打印,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
Run Code Online (Sandbox Code Playgroud)

那么它的回报价值优化?

Dea*_*ght 1

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

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

我变了

B x=b+2;
Run Code Online (Sandbox Code Playgroud)

B x(b+2);
Run Code Online (Sandbox Code Playgroud)

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

如果你改变

B x(b+2);
Run Code Online (Sandbox Code Playgroud)

B x(b);
Run Code Online (Sandbox Code Playgroud)

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

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

希望这可以帮助。