在对类对象的赋值进行链接时获取垃圾值,使用按值返回类对象的赋值运算符重载

Getting garbage value while doing chaining of assignment of class objects, using assignment operator overloading which returns class object by value

本文关键字:对象 赋值运算符 重载 返回 获取 赋值 链接      更新时间:2023-10-16

在赋值运算符重载中,如果我通过引用返回对象,如下所示

One& operator=( const One&  obj).

然后程序工作正常。

但是,如果我按值返回时,如下所示

One operator=( const One&  obj)

然后 o1 得到垃圾值。谁能解释为什么按值返回在赋值运算符重载中不起作用?

class One
{
    public:
        One(int a1, int b1) {  
            a = a1; b = b1; 
        }
        int a;
        int b;
        One operator=( const One&  obj) { 
            cout<<"nOperator= is calledn"; a = obj.a; b = obj.b; 
        }
};

int main()
{
    One o1(5,5);
    One o2(10,10);
    One o3(15,15);
    cout << "no1.a=" << o1.a << ", o1.b=" << o1.b << endl;
    o1 = o2 = o3;
    cout << "no1.a=" <<o1.a << ", o1.b=" << o1.b << endl;
    cout << "no2.a=" <<o2.a << ", o2.b=" << o2.b << endl;
    cout << "no3.a=" <<o3.a << ", o3.b=" << o3.b << endl;

    return 0;
}

输出:

o1.a=-13360, o1.b=0
o2.a=15, o2.b=15
o3.a=15, o3.b=15

为什么 o1 对象在赋值运算符中按值返回的情况下显示垃圾值。通过引用返回时工作正常。为什么?

o1 = o2 = o3;

评估为o1 = (o2 = o3);

这需要o2 = o3返回一些东西,o1设置为该值。但是您的过载目前没有。(形式上这意味着代码的行为是未定义的(。如果重写为

 One& operator=(const One& obj)
 {
     std::cout << "nOperator= is calledn";
     a = obj.a;
     b = obj.b;
     return *this; // i.e. return a reference to self.
 }

那么一切都会好起来的。也就是说,很酷的猫会使用

 One& operator=(One obj/*pass by value to exploit compiler optimisations*/)
 {
     std::cout << "nOperator= is calledn";
     std::swap(*this, obj);
     return *this;
 }

参考:什么是复制和交换成语?

=运算符的代码应该是这样的:

One & operator=(const One&  obj)
{
  cout << "nOperator= is calledn";
  a = obj.a;
  b = obj.b;
  return *this;
}
 One operator=( const One&  obj)
 { cout<<"nOperator= is calledn"; a = obj.a; b = obj.b; }

函数定义中没有任何返回表达式,从而导致未定义的行为。这就是为什么操作员不能正常工作的原因。

如果您使用的是gcc编译器,我建议您启用-Wall选项,这将产生警告,指示失败。如果您使用的是不同的,则可能有一个等效的选项可用。

您可能还想查看复制和交换习惯用法,它提供了创建正常工作的复制分配运算符的高级见解。