开发者

Function returning variable by reference?

In C++,

function() = 10;

Works if function retur开发者_StackOverflowns a variable by reference, right?

Would someone please elaborate on this in detail?


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.


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?


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;
}


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.


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;


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.


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)

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜