简体   繁体   English

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

[英]Why a reference is returned in an assignment operator overload?

I read that, reference is returned from a overloaded assignment operator to enable operator chaining. 我读到,引用是从重载的赋值运算符返回的,以启用运算符链接。 But without that return also, operator chaining seems to work. 但是,如果没有这种回报,运营商链似乎也可以奏效。

Can someone shed some light on this? 有人可以阐明这一点吗?

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;
}

Output: 输出:

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

You're running into undefined behavior because the return type expected from operator = is const A& and you're not returning anything. 您正在遇到未定义的行为,因为operator =期望的返回类型为const A&并且没有返回任何内容。

It's just unlucky that it works for you. 不幸的是它为您工作。 (yes, unlucky, because undefined behavior that appears to work is the worst) (是的,很不幸,因为似乎有效的未定义行为是最糟糕的)

I get a compile error in MSVS, and ideone.com runs into a runtime error. 我在MSVS中遇到编译错误,ideone.com遇到运行时错误。

http://ideone.com/xTDb6 http://ideone.com/xTDb6

This rule originated from code something like this: 此规则源自如下代码:

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

At that time, two things were different about C++: 当时,C ++有两点不同:

  1. The compiler-generated operator= returned an rvalue by default, and 默认情况下,由编译器生成的operator =返回一个右值,并且
  2. The compiler allowed a non-const reference to bind to a temporary. 编译器允许非常量引用绑定到临时对象。

The code above was intended to be equivalent to: 上面的代码旨在等同于:

*this = x;
return *this;

But, it wasn't -- since operator= returned an rvalue, the compiler generated a temporary to hold the result of the assignment, then since the function returned a reference, it returned a reference to that temporary. 但是,这不是-因为operator=返回了一个右值,编译器生成了一个临时变量来保存赋值结果,然后由于该函数返回了引用,因此它返回了对该临时变量的引用。 Then, of course, things went badly in a hurry, because you now had a dangling reference to a temporary that was destroyed at the end of the full expression in which it was created. 然后,当然,事情匆匆忙忙,因为您现在悬而未决地引用了一个临时对象,该临时对象在创建它的完整表达式的末尾被销毁了。 In short, a class case of returning a reference to a local -- except that it took quite a bit of analysis to realize that the local was being generated at all, not to mention a reference to it being returned. 简而言之,这是一个返回对本地的引用的类情况-除了需要花大量的分析才能意识到本地正在生成时,更不用说对它的引用了。

If you define your operator= to return a value instead of a reference, it's going to have to generate a temporary, just like the compiler did in the code above. 如果定义operator=返回值而不是引用,则必须生成一个临时值,就像编译器在上面的代码中所做的一样。 I haven't thought through the rest in detail to figure out whether the other changes in the current language would be enough to protect you in a case like this, but my immediate reaction is that you're about halfway to reconstituting that ancient bug, so unless you have absolutely no choice in the matter, I'd stay well away. 我没有仔细考虑其余的内容,以弄清楚在这种情况下当前语言的其他更改是否足以保护您,但是我的直接反应是,您大约要重新构造那个古老的bug,因此,除非您在此问题上别无选择,否则我会远离的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM