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)
精彩评论