4

I've been learning C++ but I'm having trouble understanding the way objects are returned by a member function/method. I'm following the 'Teach yourself C++ in 21 days' book.

So, I understand classes and objects, just not much about returning an object. I'll provide an example (currently learning operator overloading).

const Counter& Counter::operator++()
{
    ++itsVal;
    return *this;
}

I'm just really confused about the return type. This method says it should return a reference to a counter object, but when the object is dereferenced with

return *this;

Aren't we just returning an object of the class Counter? Why does the function header say we're returning a reference to a counter object? Why doesn't the method header just say that the return type is an object of type Counter? This is where I get confused :\

The way I'm thinking about it is that since a reference is basically an alias to something, returning a dereferenced pointer would be like returning the objects alias as objects have names which help us identify them. I dont really know, I hope someone here can explain this to me.

songyuanyao
  • 169,198
  • 16
  • 310
  • 405
Pistax
  • 51
  • 4
  • 1
    returning "object of class Couter" will create copy (a second instance), in this way of programming main idea is to have dot operator for the same instance of object. Sorry my english, cannot explain more. – Jacek Cz Sep 03 '16 at 12:51
  • 1
    agree with @Sam Varshavchik , multiple dot operator technique is advanced (such notation is part of this). Learn basic by value / by reference example. – Jacek Cz Sep 03 '16 at 13:01
  • 1
    Are you sure there's a `const`? It's highly unconventional & impractical, and unlike the built-in prefix `++`. – Cheers and hth. - Alf Sep 03 '16 at 13:12
  • Yes, I've got the PDF version of the book, and copied the function definition itself. There is, indeed, a 'const' there – Pistax Sep 03 '16 at 13:14

4 Answers4

5

Aren't we just returning an object of the class Counter?

Yes, we're returning an object. But, it's returned by reference, or by value, is determined by the return type in function declaration, we can't determine (or distinguish) them in return statement.

const Counter& Counter::operator++() // return by reference (to const)
{
    ++itsVal;
    return *this;
}

Counter Counter::operator++()        // return by value. Note the body of function is the same.
{
    ++itsVal;
    return *this;
}

BTW: Returning by reference to const (and by value, the above sample is just used for illustration) for prefix operator++ doesn't make sense. It should return reference to non-const actually. Such as

Counter& Counter::operator++() // return by reference (to non-const)
{
    ++itsVal;
    return *this;
}
songyuanyao
  • 169,198
  • 16
  • 310
  • 405
  • 3
    BTW: Learning C++ by "Teach yourself C++ in 21 days" seems to be a bad idea. – songyuanyao Sep 03 '16 at 13:06
  • Why is that? Have you heard bad things about the book? – Pistax Sep 03 '16 at 13:12
  • 3
    @Pistax (1) It's misleading. It's impossible to grasp C++ in 21 days. (2) Check [here](http://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list) for a better book. – songyuanyao Sep 03 '16 at 13:16
  • Yeah I guess so, seeing as the language is very big. I think ill go for 'Programming: Principles and Practice Using C++ (2nd Edition) 2nd Edition'. Seems like a good book for beginners. What's your opinion on it, if any? – Pistax Sep 03 '16 at 13:24
  • 2
    @Pistax Yes, it's a good book for beginner. Might be harder than "... in 21 days", it's worth. BTW: See my edited answer, returning reference to const doesn't make sense here. It might be one of the faults of the book. – songyuanyao Sep 03 '16 at 13:29
  • 1
    Well...that explains why I'm not understanding some of the stuff the author is doing here. Thank you very much for pointing out these flaws. I think I'll have to get started on the other book then. Really appreciate the help from you, and the others :] – Pistax Sep 03 '16 at 13:35
  • 1
    @Pistax Oh, reading that book seems harder. Anyway, good luck, after change the book. :) – songyuanyao Sep 03 '16 at 14:07
2

The way I'm thinking about it is that since a reference is basically an alias to something, returning a dereferenced pointer would be like returning the objects alias

Yes, that is exactly right. The function returns an alias to the object the function was called on. It does not make a copy of that object to return.

The calling code might look like:

Counter c;
do_something( ++c + 5 );

Since ++c returned an alias to c, this code will behave like:

++c;
do_something( c + 5 );

without making any unnecessary copies of c.

M.M
  • 138,810
  • 21
  • 208
  • 365
1

return *this;

Aren't we just returning an object of the class Counter?

No, this returns a reference to the object.

The * operator is the dereference operator. The result of this operator is a reference to the object the pointer is pointing to. this is a pointer.

The thing about references is that when used in a non-reference context, they automatically end up getting "converted" to the referenced object.

T *t;

// ...

T u = *t;

The result of the * operator is, as I said, a reference. Then, the result is used in a non-reference context, namely assignment to another object that, itself, is not a reference. This ends up resolving to the referenced object, resulting in a copy.

Introductory C++ primers will often state that '*p' resolves to the object the pointer is pointing to. This is just a small white lie. This is true only in a non-reference context. This leaves the intermediate step of resolving to a reference, and then resolving the reference to the referenced object.

At this point, in a typical introductory C++ primer references have not yet been brought up as a topic. So this intermediate step is left out in order to avoid confusion. But now that you know something about references, you need to do some mental gear realignment:

* gives you a reference to the object the pointer is pointing to. When used in a reference context: that is, assigning the result to a reference, passing the result as a parameter to a function that's a reference, or returning a reference from a function, you get that reference. In all other, non-reference contexts, you will end up getting the object the reference is referring to, which will typically involve making a copy of the object.

Sam Varshavchik
  • 114,536
  • 5
  • 94
  • 148
  • The result of `*t` is an lvalue of type `T`. Not a reference (whatever that is supposed to mean), certainly not `T&`. There's no such thing as "reference context" and "non-reference context". Every part of your answer is nonsensical and confusing. – M.M Sep 03 '16 at 14:02
1

The method returns the class object itself after the object being modified with itsVal plus 1.

You can use counter_object++ to self-Increment, then call some function else. Such as (counter_object++).func(), without creating another object.

songyuanyao
  • 169,198
  • 16
  • 310
  • 405
Tingur
  • 162
  • 2
  • 11