Overloading assignment operator in C++

后端 未结 10 1163
春和景丽
春和景丽 2020-11-30 04:48

As I\'ve understand, when overloading operator=, the return value should should be a non-const reference.


A& A::operator=( const A& )
{
    // check for sel         


        
相关标签:
10条回答
  • 2020-11-30 05:28

    A good general advice when overloading operators is 'do as primitive types do', and the default behavior of assignment to a primitive type is that.

    Not returning anything could be an option, to disable assignment inside other expressions if you feel the need, but returning a copy does not make sense at all: if the caller wants to make a copy they can make it out of the reference, if they do not need the copy there is no need to generate a temporary that is not needed.

    0 讨论(0)
  • 2020-11-30 05:30

    This is Item 10 of Scott Meyers' excellent book, Effective C++. Returning a reference from operator= is only a convention, but it's a good one.

    This is only a convention; code that doesn't follow it will compile. However, the convention is followed by all the built-in types as well as by all the types in the standard library. Unless you have a good reason for doing things differently, don't.

    0 讨论(0)
  • 2020-11-30 05:34

    If your assignment operator does not take a const reference parameter:

    A& A::operator=(A&); // unusual, but std::auto_ptr does this for example.
    

    or if the class A has mutable members (reference count?), then it is possible that the assignment operator changes the object being assigned from as well as assigned to. Then if you had code like this:

    a = b = c;
    

    The b = c assignment would occur first, and return a copy (call it b') by value instead of returning a reference to b. When the a = b' assignment is done, the mutating assignment operator would change the b' copy instead of the real b.

    Another potential problem -- returning by value instead of by reference could cause slicing if you have virtual assignment operators. I'm not saying that's a good idea, but it could be a problem.

    If you intend to do something like (a = b).f() then you will want it to return by reference so that if f() mutates the object, it is not mutating a temporary.

    0 讨论(0)
  • 2020-11-30 05:34

    If you're worried that returning the wrong thing might silently cause unintended side effects, you could write your operator=() to return void. I've seen a fair bit of code that does this (I assume out of laziness or just not knowing what the return type should be rather than for 'safety'), and it causes few problems. The kind of expressions that need to use the reference normally returned by operator=() are pretty rarely used, and almost always easy code an alternative for.

    I'm not sure I'd endorse returning void (in a code review I'd probably call it out as something you shouldn't do), but I'm throwing it out there as an option to consider if you want to not have to worry about how oddball uses of the assignment operator might be handled.


    late edit:

    Also, I should have originally mentioned that you can split the difference by having your operator=() return a const& - that will still permit assignment chaining:

    a = b = c;
    

    But will disallow some of the more unusual uses:

    (a = b) = c;
    

    Note that this makes the assignment operator have semantics similar to what it has in C, where the value returned by the = operator is not an lvalue. In C++, the standard changed it so the = operator returns the type of the left operand, so it is an lvalue, but as Steve Jessop noted in a comment to another answer, while that makes it so the compiler will accept

    (a = b) = c;
    

    even for built-ins, the result is undefined behavior for built-ins since a is modified twice with no intervening sequence point. That problem is avoided for non-builtins with an operator=() because the operator=() function call is a sequence point.

    0 讨论(0)
  • 2020-11-30 05:38

    Cause f() can modify a. (we return a non-const reference)

    If we return a value (a copy) of a, f() will modify the copy, not a

    0 讨论(0)
  • 2020-11-30 05:42

    Not returning a reference is a waste of resources and a yields a weird design. Why do you want to do a copy for all users of your operator even if almost all of them will discard that value?

    a = b; // huh, why does this create an unnecessary copy?
    

    In addition, it would be surprising to users of your class, since the built-in assignment operator doesn't copy likewise

    int &a = (some_int = 0); // works
    
    0 讨论(0)
提交回复
热议问题