为什么我在显式编写复制构造函数后得到垃圾值?

Why I'm getting garbage value after explicitly writing the Copy Constructor?

我有一个程序使用 + 运算符重载将两个复数相加。程序是:

#include<iostream>
class Complex
{
  int a, b;
  public:
  Complex()
  {
    std::cout<<"\n Normal constructor ";
  }
  void setData(int x, int y)
  {
    a = x; b = y;
  }
  void showData()
  {
    std::cout<<"a = "<<a<<std::endl<<"b = "<<b<<std::endl;
  }
  Complex operator + (Complex c)
  {
    Complex temp;
    temp.a = a + c.a;
    temp.b = b + c.b;
    return temp;
  }
  Complex(Complex &z)
  {
    std::cout<<"\n The copy constructor is called ";
  }
};
int main()
{
  Complex c1, c2, c3;
  c1.setData(2, 3);
  c2.setData(4, 5);
  c3 = c1+c2;
  c3.showData();
  return 0;
}

在这里,当我没有显式地编写复制构造函数时,这个程序给出了正确的输出。但是在写了copy constructor之后输出的是垃圾值,我想知道为什么程序会产生垃圾值?

输出实例:

Normal constructor 
 Normal constructor 
 Normal constructor 
 The copy constructor is called 
 Normal constructor a = -1270468398
b = 32769

请告诉"what is happening after c3 = c1+2; is executed?"

您忘记在复制构造函数中复制成员。如果您自己编写,则必须这样做。因为你没有默认初始化成员,在 int 的情况下,这意味着没有初始化发生,所以你有一个垃圾值。

你的复制构造函数应该是

Complex(const Complex &z) : a(z.a), b(z.b)
{
    std::cout<<"\n The copy constructor is called ";
}

你还应该通过const&把要复制的对象也带进去,这样你就可以复制临时对象了。 Complex(Complex &z) 做不到。

您没有在复制构造函数中初始化成员数据。

添加代码以初始化成员。

Complex(Complex &z) : a(z.a), b(z.b)
{
   std::cout<<"\n The copy constructor is called ";
}

此外,您应该将参数设为 const& 类型的复制构造。

Complex(Complex const& z) : a(z.a), b(z.b)
{
   std::cout<<"\n The copy constructor is called ";
}

c2 传递给 operator + 时调用复制构造函数。

有两个选项可以解决您的问题(但无论如何都应该解决):

operator+ 应该采用 const 引用而不是对象的副本:

Complex operator + (const Complex &c)

你的复制构造函数应该真正复制对象(除了将 const 引用作为参数):

Complex(const Complex &z) : a (z.a), b(z.b)

您的代码还有其他一些评论要完成

  • 首先我希望这只是一个练习,因为 std::complex 存在
  • 你的默认构造函数应该初始化成员
  • setData / showData 似乎是错误的,你应该有有意义的访问器来隐藏你的内部(一个复杂的可以用实部/虚部来表示,也可以用模块/参数等来表示......)
  • showData 应该是 const(它不是修改对象,它应该可以在 const 对象上调用)

希望对您有所帮助。

在您的情况下,由于您没有任何要执行深复制的指针,因此编译器生成的复制构造函数就足够了。

为了提高可读性,在版本 >= c++11 的情况下,您可以明确地使用它

Complex(Complex const&) = default;

回答你的问题,当 "c3 = c1+c2;"

时会发生什么

函数 "operator +" 将在 C1 对象上调用,因此这里 C2 将被复制到参数 "Complex c".. 所以你得到调用的复制构造函数

形象化是这样

Comlex operator+(Complex c(c2)/* copy constructor is called here*/)
{
    ...
    return temp.
}

然后operator= 函数被调用,temp 将被分配给C3。如果重载operator=,可以看到对它的调用