Returning References from functions
Objectives
We would like to :- Discuss returning a reference from a function.
Notes
- Continued chapter 7 from the book, and other sources.
- Code is in referenceReturn.cpp.
- We saw that the overloaded stream insertion operator returned a reference.
-
ostream & operator << (ostream & s, const SomeDataT & other){ s << other.Data(); return s; } ... SomeDataT data; ... cout << data; - The compiler will pass in a reference to
coutand todata - On return, it will return a reference to
cout - So returning a reference
-
- Why did we return a reference in this case?
- The book describes it as cascading use.
- There are other functions we expect to return a reference
- ++i is one case.
- += is another.
- = is another
- [] is another in 1/2 the cases.
- There are a few others, but you are unlikely to use those now.
- A word about ++i and i++ before we continue
- ++i is called the prefix increment.
- The prefix operator:
- Changes the value
- And returns the new value.
-
The code: int i{10}; int j; j = i; cout << "i = " << i << " j = " << j << endl; cout << endl; cout << "j = ++i" << endl; j = ++i; cout << "i = " << i << " j = " << j << endl; produces i = 10 j = 10 j = ++i i = 11 j = 11
- The prefix operator:
- i++ is called the postfix increment.
- This increments the variable
- But returns the old value.
-
i = 11; cout << "j = ++i" << endl; j = ++i; cout << "i = " << i << " j = " << j << endl; produces j = i++ i = 12 j = 11
- ++i is called the prefix increment.
- Overloading these is easy, but there is a "trick".
- In the case of prefix, it makes sense to return a reference
- In the case of postfix, it does not.
- But return type is not part of the function signature, so Stroustrup added a "fake" parameter to the postfix operator.
- The two prototyptes are
-
SomeDataT & operator ++(); SomeDataT operator ++(int);
-
- There is no parameter passed to the second, it is just used to mark the difference.
- But we do have to deal with
this-
thisis a member of every class. - It is a pointer to the current instance.
- We will use it in both of the ++ functions.
-
- The functions
-
SomeDataT operator ++(int) { SomeDataT originalValue{*this}; ++data; return originalValue; } SomeDataT & operator ++() { ++data; return *this; }
- You might get tempted to return references to everything
- Which is ok, but we need to be careful
- Remember, this is returning a pointer to memory.
- And we need to make sure that that memory is still valid.
- But why would memory no longer be valid?
- Local variables are
- Allocated when we declare them
- Deallocated when they go out of lifetime.
- So we can not return a reference to a local variable.
- Consider
SomeDataT & GoodFunction(SomeDataT & other){ return other; } SomeDataT & BadFunction(SomeDataT other){ return other; }
- Which is ok, but we need to be careful