Overloading assignment operator in C++

2020-01-27 04:06发布

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


A& A::operator=( const A& )
{
    // check for self-assignment, do assignment

    return *this;
}

It is non-const to allow non-const member functions to be called in cases like:


( a = b ).f();

But why should it return a reference? In what instance will it give a problem if the return value is not declared a reference, let's say return by value?

It's assumed that copy constructor is implemented correctly.

10条回答
Ridiculous、
2楼-- · 2020-01-27 04:41

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.

查看更多
神经病院院长
3楼-- · 2020-01-27 04:41

Returning by reference reduces the time of performing chained operations. E. g. :

a = b = c = d;

Let's see the actions which would be called, if operator= returns by value.

  1. Copy assignment opertor= for c makes c equal to d and then creates temporary anonymous object (calls copy ctor). Let's call it tc.
  2. Then operator= for b is called. Right hand side object is tc. Move assignment operator is called. b becomes equal to tc. And then function copies b to temporary anonymous, let's call it tb.
  3. The same thing happens again, a.operator= returns temporary copy of a. After operator ; all three temporary objects are destroyed

Altogether: 3 copy ctors, 2 move operators, 1 copy operator

Let's see what will change if operator= will return value by reference:

  1. Copy assignment operator is called. c becomes equal to d, reference to lvalue object is returned
  2. The same. b becomes equal to c, reference to lvalue object is returned
  3. The same. a becomes equal to b, reference to lvalue object is returned

Altogether: only three copy operators is called and no ctors at all!

Moreover I recommend you to return value by const reference, it won't allow you to write tricky and unobvious code. With cleaner code finding bugs will be much easier :) ( a = b ).f(); is better to split to two lines a=b; a.f();.

P.S.: Copy assignment operator : operator=(const Class& rhs).

Move assignment operator : operator=(Class&& rhs).

查看更多
Lonely孤独者°
4楼-- · 2020-01-27 04:42

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.

查看更多
姐就是有狂的资本
5楼-- · 2020-01-27 04:43

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.

查看更多
登录 后发表回答