开发者

Rvalues vs temporaries

Somebody generalized the statement "Temporaries are rvalues". I said "no" and gave him the following example

 double k=3;

 double& foo()
 {
    return k;
 }

 int main()
 {开发者_如何转开发

     foo()=3; //foo() creates a temporary which is an lvalue
 }

Is my interpretation correct?


Temporaries and rvalues are different (but related) concepts. Being temporary is a property of an object. Examples of objects that aren't tempory are local objects, global objects and dynamically created objects.

Being an rvalue is a property of an expression. The opposite of rvalues are lvalues such as names or dereferenced pointers. The statement "Temporaries are rvalues" is meaningless. Here is the relationsip between rvalues and temporary objects:

An rvalue is an expression whose evaluation creates a temporary object which is destroyed at the end of the full-expression that lexically contains the rvalue.

Note that lvalues can also denote temporary objects!

void blah(const std::string& s);

blah(std::string("test"));

Inside the function blah, the lvalue s denotes the temporary object created by evaluating the expression std::string("test").

Your comment "references are lvalues" is also meaningless. A reference is not an expression and thus cannot be an lvalue. What you really mean is:

The expression function() is an lvalue if the function returns a reference.


No. You are returning a reference to an global double, not a temporary.

The same test with a real temporary would be:

double foo() { return 3.0; }
int main() {
   foo() = 2.0; // error: lvalue required as left operand of assignment
}

EDIT: The answer was meant just to identify that the example was wrong, and I did not really want to get into the deeper discussion of whether temporaries are or not rvalues... As others have said, lvalue-ness or rvalue-ness are properties of an expression and not of the object (in the most general sense, not only class instances). Then again, the standard says that:

§3.10/5 The result of calling a function that does not return a reference is an rvalue. User defined operators are functions, and whether such operators expect or yield lvalues is determined by their parameter and return types.

§3.10/6 An expression which holds a temporary object resulting from a cast to a nonreference type is an rvalue (this includes the explicit creation of an object using functional notation (5.2.3)).

Which AFAIK are the circumstances under which temporaries are created. Now, it is also true that you can bind a constant reference to a temporary, in which case you will get a new variable (the reference) that can be used as an lvalue that effectively refers to the temporary object.

The fine line is that expressions that create temporaries are rvalue expressions. You can bind a constant reference to the result of that expression to obtain a variable that can be used as an const-qualified lvalue expression.


Temporaries were so consistently protected from becoming lvalues, that they are now called rvalues. But C++0x will allow temporaries to become lvalues thanks to move semantics. Like in this dumb snippet

void blah(ICanBeTemporary && temp)
{
    temp.data = 2; //here temporary becomes lvalue
}


//somewhere
blah(ICanBeTemporary("yes I can"));

Now we have terminology mess. People used to call temporaries rvalues and this is called rvalue reference. Named objects are now considered to be non-rvalue referenced.

0

上一篇:

下一篇:

精彩评论

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

最新问答

问答排行榜