为什么在赋值运算符重载中返回引用?

时间:2012-04-30 07:50:12

标签: c++ operator-overloading chaining assignment-operator

我读过,从重载的赋值运算符返回引用以启用运算符链接。但如果没有这种回报,操作员链接似乎也有效。

有人可以对此有所了解吗?

class A
{
    public:
        int x,y;
        char* str;

        //Default Constructor
        A(){}

        //Constructor
        A(int a, int b, char* s){
            cout<<"initialising\n";
            x = a;
            y = b;
            str = new char[10];
            str = s;
        }

        //Destructor
        ~A(){}

        //Overloaded assignment operator
        const A& operator=(const A& obj)
        {
            cout<<"Invoking Assignment Operator\n";
            x = obj.x;
            y = obj.y;
            str = new char[10];
            str = obj.str;

            //return *this;
        }
};

ostream& operator<<(ostream& os, const A& obj)
{
    os <<"X="<< obj.x<<" Y="<<obj.y<<" Str="<<obj.str<<"\n";
    return os;
}

int main()
{
    A c(3,4,"Object C");
    cout<<c;

    A d, e, f;
    d = e = f = c;  //Assignment operator invoked 3 times
    cout<<e;
}

输出:

initialising
X=3 Y=4 Str=Object C
Invoking Assignment Operator
Invoking Assignment Operator
Invoking Assignment Operator
X=3 Y=4 Str=Object C

2 个答案:

答案 0 :(得分:2)

您正在遇到未定义的行为,因为operator =预期的返回类型为const A&而您没有返回任何内容。

它很不幸,它适合你。 (是的,不幸的是,因为看似有效的未定义行为是最糟糕的)

我在MSVS中遇到编译错误,并且ideone.com遇到运行时错误。

http://ideone.com/xTDb6

答案 1 :(得分:2)

此规则源自以下代码:

struct Foo { 
    Foo& copy(const Foo& x) { 
        return (*this = x); 
    } 
};

当时,C ++有两件事情不同:

  1. 编译器生成的operator =默认返回rvalue,
  2. 编译器允许非const引用绑定到临时引用。
  3. 上述代码旨在等同于:

    *this = x;
    return *this;
    

    但是,它不是 - 因为operator=返回了一个rvalue,编译器生成了一个临时来保存赋值的结果,然后由于函数返回了一个引用,它返回了对该临时值的引用。然后,当然,事情变得非常匆忙,因为你现在有一个悬挂的引用,它在创建它的完整表达式的末尾被破坏了。简而言之,是一个返回对本地的引用的类案例 - 除了需要进行相当多的分析才能意识到本地正在生成,更不用说对它的引用被返回了。

    如果你定义你的operator=来返回一个值而不是一个引用,它就必须生成一个临时的,就像编译器在上面的代码中所做的那样。我没有仔细考虑其余部分来弄清楚当前语言中的其他变化是否足以在这样的情况下保护你,但我的直接反应是你要重建那个古老的虫子,所以,除非你在这件事上绝对没有选择,否则我会保持良好状态。