tags:

views:

299

answers:

7

In C++,

function() = 10;

Works if function returns a variable by reference, right?

Would someone please elaborate on this in detail?

+15  A: 

Consider this piece of code first

int *function();
...
*function() = 10;

Looks similar, isn't it? In this example, function returns a pointer to int, and you can use it in the above way by applying a unary * operator to it.

Now, in this particular context you can think of references as "pointers in disguise". I.e. reference is a "pointer", except that you don't need to apply the * operator to it

int &function();
...
function() = 10;

In general, it is not a very good idea to equate references to pointers, but for this particular explanation it works very well.

AndreyT
+1 for getting in there before me. Great minds and all that :)
Binary Worrier
Nice job using a not-quite-correct but nonetheless appropriate analogy to clearly explain it, while also pointing out the danger of using not-quite-correct analogies in general :)
Pavel Minaev
+6  A: 

Consider the following code, MyFunction returns a pointer to an int, and you set a value to the int.

int  *i;
i = MyFunction();
*i = 10;

Are you with me so far?

Now shorten that to

*(MyFunction()) = 10;

It does exactly the same thing as the first code block.

You can look at a reference as just a pointer that's always dereferenced. So if my function returned a reference - not a pointer - to an int the frist code block would become

int  &i;
i = MyFunction();
i = 10;

and the second would become

MyFunction() = 10;

You still with me?

Binary Worrier
+1  A: 

With a little experiment, you can determine if this will work or not.

Considering this example:

class foo {
    private:
        int _val;
    public:
        foo() { _val = 0; }
        int& get() { return _val; }
        void print() { printf("val: %d\n", _val); }
};

int main(void) {
    foo bar;
    bar.print();
    bar.get() = 10;
    bar.print();
}

And it's output is:

val: 0
val: 10

So sure enough, it is possible to return a reference. Note that the variable being referenced may go out of scope, then your caller may get garbage results (just like dereferencing a pointer to an object that has gone out of scope). So this would be bad:

int& get() {
    int myval = _val;
    return myval;
}
jheddings
+1  A: 

The answer to this question has to do with rvalue semantics versus lvalue semantics. Every value in C++ is either an lvalue or an rvalue. Lvalues are values that are stored in an addressable memory location, which implies they are assignable (assuming they are non-const, of course.) An rvalue is basically anything else, e..g literal constants, or non-addressable temporary values.

So, a function which returns a non-const reference is an lvalue. However, a function which returns by value would be an rvalue expression, because it returns a non-addressable temporary value, and is therefore not assignable.

See the wikipedia entry for a more detailed explanation with examples given.

Charles Salvia
A: 

As others noted function can return reference to member variable, but word of caution: this function should not be a part of class interface. Once you provide a function that returns reference to internals of your class, you loose control over them. If you have not yet read "Effective C++", do it. Item 29 of the book says "Avoid returning "handles" to internal data" and explains in more details why this practice needs to be avoided.

BostonLogan
How do you overload operator[] without violating that rule?
Fred
Good point Fred, but semantics of [] (non-const) suggests that operator is mutator. And usually used as such, i.e. x[5] = 10; But it can be abused of course, such as int (and used later... ouch...)But this is price you pay for the convenience of [];
BostonLogan
+1  A: 

A question you did not ask.
But why would you want to do that?

Think of the std::vector (I am extending the principle to methods).

Here you have the method 'operator[]()' It retuns a reference to the internal member.
This then allows the following:

std::vector<int>  x(20,1);
x[5] = 10;

// This is quivalent to:
x.operator[](5) = 10;

// So this is just a function (method) call:
x.function(5) = 10;
Martin York
A: 

A word of warning, when returning a reference: pay attention to the lifetime of whatever you're returning. This example is bad:

int &function()
{
    int x;
    // BAD CODE!
    return x;
}
...
function() = 10;

x doesn't exist outside of function, and neither do any references to it. In order to return a reference from a function, the object being referred to has to last at least as long as the reference. In the above example, x would need to be declared static. Other possibilities would be making x a global variable, or making function a class member function and returning a reference to a class member variable, or allocating x on the heap and returning a reference to that (although that gets tricky with deallocation)

Eclipse
I don't understand why you see this as something specific to non-const references only. In this particular example returning any reference (const or not) would lead to the same problem.
AndreyT
Um, yes, thanks - a little spaced out today. I mentioned non-const, since you can't modify a const reference anyway, but that doesn't much matter in the context of the rest of what I said.
Eclipse