4

I went over making my own copy constructor and it overall makes sense to me. However, on the topic of doing your own assignment operator I need someone to fill in the blank for me.

I pretty much don't get why you are returning *this in all the examples, such as the one below:

Foo & Foo::operator=(const Foo & f)
{

//some logic

return *this;

}

So if I have some statements like:

Foo f;
f.hour = 7;

Foo g;
g = f;

Once the assignment operator runs, it returns a reference to the g object (the *this). So now the question is, won't I now have a statement implicitly like this?:

g = g (g being a reference)

The thing is, before, setting a reference to just an object would have caused the copy constructor to be invoked. In this case, it doesn't even though it fits the signature of the copy constructor.

J. Polfer
  • 12,251
  • 10
  • 54
  • 83
Ilya
  • 1,215
  • 1
  • 14
  • 25
  • 1
    Remember to check for self-assignment! (see http://www.parashift.com/c++-faq-lite/assignment-operators.html#faq-12.1) – In silico Jul 14 '10 at 16:48
  • 3
    @In silico: Alternatively, write your assignment operators so they'll work with self-assignment (which is frequently a result of having exception-safe assignment operators). – David Thornley Jul 14 '10 at 16:50
  • My question though even beyond *this is: If I've returned a reference to an object and am storing it into an ordinary object, what will happen if the copy constructor is not called. In my case, I already wrote up the assignment operator so the copy constructor will not be called. – Ilya Jul 14 '10 at 16:56
  • Look up the copy swap idium for implementing assignment operator. It is exception safe and means you do not need to explicitly check for assignment to self (unless you want too). – Martin York Jul 14 '10 at 17:33

4 Answers4

8

You want to return *this so you can chain =:

Foo f, g, h;

f = g = h;

This is basically assigning h into g, then assigning g (returned by return *this) into f:

f = (g = h);

Another situation this is sometimes used in is having an assignment in a conditional (considered bad style by many):

if ( (f = 3).isOK() ) {

With the statement g = f; the return is just ignored, like if you did 3 + 4;.

Donald Miner
  • 38,889
  • 8
  • 95
  • 118
4

I think you're confusing the idea of infix notation a bit. g = f does not mean call operator= of g with f and put the result into g it means apply operator= on g with parameter f and set the value of this expression to the result. This is identical behavior to the other infix operators such as + or /.

Operators in some languages can be applied like a normal function (and in C++ with some extraneous syntax) such as = (g f) which shows the concept a bit more clearly.

Edit:

For example, what is often used as an example for IO:

// loop until some sentinel value
while ((nextChar = (char) getchar()) != 'Q') {
  string += nextChar;
}

Notice that because the = operator returns its first argument (nextChar in this example) you can compose the assignment and testing.

Ron Warholic
  • 9,994
  • 31
  • 47
0

Once the assignment operator runs, it returns a reference to the g object (the *this). So now the question is, won't I now have a statement implicitly like this?:

g = g (g being a reference)

No, but self assignment is something you need to check for. What returning *this does is make the value of the expression (g=f), g. Which is useful for chaining assignments. In a statement like

Foo a, b, c;
a = b = c;

a is being assigned the return value from the method operator=. Returning *this makes this statement do what is expected (the value of c is assigned to b, then the new value of b is assigned to a).

Graphics Noob
  • 9,790
  • 11
  • 46
  • 44
0

The reason is so that the result of your assignment can be an rvalue in another expression.

J. Polfer
  • 12,251
  • 10
  • 54
  • 83
  • 2
    The call of a function returning a reference is actually an **lvalue**. – fredoverflow Jul 14 '10 at 18:02
  • @FredOverflow: If f is a function returning a reference, then f()=5 is using f() as an lvalue. But what about a=f(); Is this using the f() result as an rvalue? a = b = c is like a = (b = c), which is analogous to a = f() – Aaron McDaid Jul 14 '10 at 23:45
  • You have linked to a C question, but the terms *lvalue* and *rvalue* have different meanings in C and C++. (Actually, there is no such thing as an "rvalue" in the current C standard.) – fredoverflow Jul 15 '10 at 14:35
  • @FredOverflow: This question/accepted answer would suggest you are incorrect: http://stackoverflow.com/questions/2038414/lvalue-and-rvalue. I think, though, that this question has motivated me to make sure I have a good+solid definition on what an lvalue and an rvalue is (from the answer in this comment, it still seems nebulous to me). – J. Polfer Jul 15 '10 at 14:36
  • @FredOverflow - This might be a stupid question but - where can I find an official definition on lvalue and rvalue in a book/site? I've looked in the indexes of K&R and Stroustrup and don't see anything; do you need the actual spec for the definition? – J. Polfer Jul 15 '10 at 14:40
  • Sadly, not a single book I own gets it right :) You must read the standard, for example the [C++0x FCD](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2010/n3092.pdf). But beware, the contained definition of rvalues and temporaries in the FCD is [controversial](http://stackoverflow.com/questions/3007728/rvalues-and-temporary-objects-in-the-fcd). – fredoverflow Jul 15 '10 at 14:47
  • @FredOverflow "_but the terms lvalue and rvalue have different meanings in C and C++._" can you point out the difference? – curiousguy Dec 25 '11 at 22:13
  • 1
    @curiousguy: Well, first of all, the C standard does not even define the term "rvalue". Standard C only knows about lvalues. But let's just pretend that C has rvalues. Here are two examples: 1. Evaluating an rvalue of struct type in C++ yields a temporary object whose lifetime is well-defined ("end of full-expression"). In C, this is not the case. I stumbled upon this [two months ago](http://stackoverflow.com/questions/7963813/). 2. It is impossible to assign to an rvalue in C. In C++, you can say `std::string("hello") = "world";` without problems, and `std::string("hello")` is an rvalue. – fredoverflow Dec 25 '11 at 22:22