Question

int& returnC() {
    return c;
}

So part of my question has been answered by another question here but I'm still a bit confused. So I know this returns a reference not an address. But what's the advantage of this definition, you're just returning c why not define it as:

int returnC() {
    return c;
}

what's the advantage of returning an reference to an int and not just an int if they both return the same variable?

what happens if I declare it like this:

int& returnC() {
    return &c;
}

Thank you!

Was it helpful?

Solution

Return by value

Return by value is the simplest and safest return type to use. When a value is returned by value, a copy of that value is returned to the caller. Eg:

int returnC() {
    return c;
}

Return by reference

Just like with pass by reference, values returned by reference must be variables (you can not return a reference to a literal or an expression). When a variable is returned by reference, a reference to the variable is passed back to the caller. The caller can then use this reference to continue modifying the variable, which can be useful at times. Return by reference is also fast, which can be useful when returning structs and classes. Eg:

// This struct holds an array of 25 integers
struct MyArrays
{
    int ArrValue[25];
};


// Returns a reference to the nIndex element of rArray
int& Value(MyArrays &rArray, int nIndex)
{
    return rArray.ArrValue[nIndex];
}

int main()
{
    MyArrays objArray;

    // Set the 10th element of objArray to the value 5
    Value(objArray, 10) = 5;

    cout << objArray.ArrValue[10] << endl;
    return 0;
}

OTHER TIPS

With the first version:

int returnC() {
    return c;
}

You are just returning a copy of c. The caller can do whatever they want with this copy and it will never affect s

with the second version (no need to take address of c):

int& returnC() {
    return c;
}

The caller would be able to write

returnC() = 5

and set the member c to 5. I'm assuming c is a data member of a class since I don't see it defined anywhere. If c isn't a data member of a class then you would be returning a reference to a temporary which wont exist when the caller of returnC tries to use it and should be avoided

To return an int I would probably use return by value. Unless I wanted the caller to be able to change c, but this leaks implementation details and is generally considered bad practise. If I wanted to return an object I might do this by const reference. This saves copying the class without giving the caller the ability to alter the object. If the caller needed to alter the object then we would be back to returning by value

It may look like returning a reference to an int is the same as returning an int, but in fact they are two fundamentally different things.

Return By Reference
When you return a reference to an Object/primitive (such as an int), you are returning a reference to the variable being returned in your method. For objects, this is advantageous since the object doesn't have to be copied and rather just a reference to that object just be returned.
It also allows you to do this:

int& max(int &x, int &y){
    if (x > y){
        return x;
    }

    return y;
}

int main(){
    int x = 10, y = 12;

    //This sets, y to 0.
    max(x, y) = 0;
}


Return By Value
When you return an Object/primitive itself (again, such as an int), you are returning a copy of the variable and not the actual variable itself. This doesn't matter as much for primitive types such as int or char but for objects, this can be a lot slower. Simply put, a copy of the object that is being returned has to be created with that object having the exact same values for attributes.

It depends on where is your variable declared. You only can return a reference if the variable has not automatic storage inside the function. I mean, you never have to do something like this:

int& foo () {
     int a = 1;
     return a;
}

In this case, a is variable with automatic storage. When function returns, the variable is lost and you have a reference to a destroyed variable, which is a very bad thing.

If you have a member variable of a class or a global one, you can return it by value or by reference. The difference is then of semantics: if you return by value, only its value is important and variable will be copied.

On the other hand, by returning a reference you allowed to modify the original data. It could be faster since no copy is required. But it is a different thing.

class MyClass {
     int a;

public:
     int& foo () { return a; }
     int foo () { return a; }
     /* ... */
};

The class MyClass has an int member a. You can return a by value or by reference. The difference here is the meaning. Are you allowing to modify the original data? If so, return by reference.

Your last example is wrong:

int& returnC() {
    return &c;
}

Your function says: "I am returning a reference to int", but return &c means you are returning a pointer to it. In that case the correct way is:

int* returnC() {
    return &c;
}

Then you are returning a pointer to int and you must not return a pointer to a automatic variable either.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top