Returning a Reference

Started by
8 comments, last by sQuid 20 years, 8 months ago
So I understand that you''d pass arguments by reference

some_function(Foo& bar);
 
to avoid making an extra copy of the argument. But, other than in member functions when you''re returning *this, when would you return by reference

Foo& another_function(Foo &bar)
 
since whatever the return value refers to will then be out of scope. Are there any other valid uses of returning a reference?
Advertisement
You might want to return a reference to a member variable of a class.


"Absorb what is useful, reject what is useless, and add what is specifically your own." - Lee Jun Fan
"Absorb what is useful, reject what is useless, and add what is specifically your own." - Lee Jun Fan
You can return a refernce to anything that is not local to your function. You could return a reference to a member variable :

class Foo{  HugeObject bar;public:  const HugeObject& Bar() const   {     return bar;   }  Foo& Bar( const HugeObject& val )   {     bar = val;     return *this;   }  friend std::ostream& operator<<( std::ostream&, const Foo& );  friend std::istream& operator>>( std::istream&, Foo& );};


Note that returning a non-const reference to a member variable is a violation of encapsulation, as the receiver of the value could use it to modify the variable as if it were public - if that''s what you want, get over it and just make it public instead of fooling yourself.

You can also return a reference to a parameter, not necessarily *this, for example to enable call chaining.

With iostreams, you need to return the stream object by reference to allow calls like
std::cout << FooObj1 << FooObj2 << FooObj3 << std::endl;

std::ostream& operator<<( std::ostream& os, const Foo& obj ){  os << obj.bar;  return os;}std::istream& operator<<( std::ostream& is, Foo& obj ){  is >> obj.bar;  return is;}


iostreams operator overloads are typically friend non-members of the class you are adding stream support for.

[ Start Here ! | How To Ask Smart Questions | Recommended C++ Books | C++ FAQ Lite | Function Ptrs | CppTips Archive ]
[ Header Files | File Format Docs | LNK2001 | C++ STL Doc | STLPort | Free C++ IDE | Boost C++ Lib | MSVC6 Lib Fixes ]
"Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it." — Brian W. Kernighan
quote:Original post by Fruny
You can also return a reference to a parameter, not necessarily *this, for example to enable call chaining.


Returning a reference to a parameter is only a good idea when the parameter is a reference itself. Otherwise it will reference the stack and something will more than likely get screwed up down the line.
Chess is played by three people. Two people play the game; the third provides moral support for the pawns. The object of the game is to kill your opponent by flinging captured pieces at his head. Since the only piece that can be killed is a pawn, the two armies agree to meet in a pawn-infested area (or even a pawn shop) and kill as many pawns as possible in the crossfire. If the game goes on for an hour, one player may legally attempt to gouge out the other player's eyes with his King.
I wouldn''t mix the use of pointers and references in your code simply because of the rule that you cannot have a NULL reference. Doing this may result in hard to find bugs.

I don''t know what the confusion is. Just make both function void for the examples you have provided and store the value in bar. The function does not need to return anything, since as you are passing by reference between the pointers they are referencing the same region of memory:

void some_function(Foo& bar);
void another_function(Foo &bar);

Foo& bar and Foo &bar are parsed as the same thing.



Beginners and experts will find answers here.
quote:Original post by Mathematix
I wouldn''t mix the use of pointers and references in your code simply because of the rule that you cannot have a NULL reference. Doing this may result in hard to find bugs.


I don''t see the problem. To try and create a null reference, you would have first to dereference a null pointer. Which is not that hard to find.

Anyway returning *this by reference is a common C++ idiom, and that''s the only pointer I see discussed here.
"Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it." — Brian W. Kernighan
quote:Original post by Fruny
quote:Original post by Mathematix
I wouldn''t mix the use of pointers and references in your code simply because of the rule that you cannot have a NULL reference. Doing this may result in hard to find bugs.


I don''t see the problem. To try and create a null reference, you would have first to dereference a null pointer. Which is not that hard to find.

Anyway returning *this by reference is a common C++ idiom, and that''s the only pointer I see discussed here.


I don''t see the justification in doing this. Can you come up with a necessary, valid scenario?



Beginners and experts will find answers here.
quote:Original post by Mathematix
I don't see the justification in doing this. Can you come up with a necessary, valid scenario?


No problem, here's one : operator overloading.

class Foo{   /* stuff */public:   Foo()  { /* stuff */ }   ~Foo() { /* stuff */ }   Foo( const Foo& ) { /* stuff */ }   Foo& operator=( const Foo& )    {       /* stuff */      return *this;    }};Foo a, b, c;...a = b = c;


The principle of least surprise mandates that, since chained assignment is possible with basic types, user-defined types should provide it too.

It also lets you give a neater syntax to "accessors & mutators"

class Foo{   int x, y, z;public:   int X() const { return x; }   int Y() const { return y; }   int Z() const { return z; }   Foo& X( int new_x ) { x = new_x; return *this; }   Foo& Y( int new_y ) { y = new_y; return *this; }   Foo& Z( int new_z ) { z = new_z; return *this; }};Foo f;f.X(10).Y(20).Z(30);int x = f.X();


Like I'm telling you, it's a common C++ idiom. If you don't believe me, check any good reference book.

To conclude, I'll point out that I only know of one way to have a null this pointer, and if you get one that's because you really asked for it.

[ Start Here ! | How To Ask Smart Questions | Recommended C++ Books | C++ FAQ Lite | Function Ptrs | CppTips Archive ]
[ Header Files | File Format Docs | LNK2001 | C++ STL Doc | STLPort | Free C++ IDE | Boost C++ Lib | MSVC6 Lib Fixes ]

[edited by - Fruny on August 14, 2003 6:00:56 PM]
"Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it." — Brian W. Kernighan
Fruny,

Typical of C++! The fuzzy standards say you can''t do something and it turns out there is a ''pseudo-way'' of doing it! LOL

I must play with this.

Beginners and experts will find answers here.
quote:Original post by Mathematix
Just make both function void for the examples you have provided and store the value in bar. The function does not need to return anything, since as you are passing by reference between the pointers they are referencing the same region of memory:


It wasn''t really a problem. I''d just seen functions returning references in Stroustrup and didn''t understand when it was appropriate and when it wasn''t.

Thanks for the replies.

This topic is closed to new replies.

Advertisement