Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

rvalue references: what exactly are "temporary" objects, what is their scope, and where are they stored?

Tags:

c++

c++11

rvalue references: what exactly are "temporary" objects, what is their scope, and where are they stored?

Reading some articles, rvalues are always defined as "temporary" objects like Animal(), where Animal is a class, or some literal e.g. 10.

However, what is the formal definition of rvalues/"temporary" objects?

Is new Animal() also considered a "temporary" object? Or is it only values on the stack, like Animal() and literals stored in code?

Also, where are these "temporary" objects stored, what is their scope, and how long are rvalue references to these values valid?

like image 887
Shuzheng Avatar asked Mar 26 '16 07:03

Shuzheng


1 Answers

Firstly it is important not to conflate the terms "rvalue" and "temporary object". They have very different meanings.


Temporary objects do not have a storage duration. Instead, they have lifetime rules that are specific to temporary objects. These can be found in section [class.temporary] of the C++ Standard; there is a summary on cppreference, which also includes a list of which expressions create temporary objects.

In practice I'd expect that a compiler would either optimize the object out, or store it in the same location as automatic objects are stored.

Note that "temporary object" only refers to objects of class type. The equivalent for built-in types are called values. (Not "temporary values"). In fact the term "values" includes both values of built-in type, and temporary objects.

A "value" is a completely separate idea to prvalue, xvalue, rvalue. The similarity in spelling is unfortunate.

Values don't have scope. Scope is a property of a name. In many cases the scope of a name coincides with the lifetime of the object or value it names, but not always.


The terms rvalue, lvalue etc. are value categories of an expression. These describe expressions, not values or objects.

Every expression has a value category. Also, every expression has a value, except expressions of void type. These are two different things. (The value of an expression has a non-reference type.)

An expression of value category rvalue may designate a temporary object, or a non-temporary object, or a value of built-in type.

The expressions which create a temporary object all have value category prvalue, however it is then possible to form expressions with category lvalue which designate that same temporary object. For example:

const std::string &v = std::string("hello");

In this case v is an lvalue, but it designates a temporary object. The lifetime of this temporary object matches the lifetime of v, as described in the earlier cppreference link.

Link to further reading about value categories


An rvalue reference is a reference that can only bind to an expression of value category rvalue. (This includes prvalue and xvalue). The word rvalue in its name refers to what it binds to, not its own value category.

All named references in fact have category lvalue. Once bound, there is no difference in behaviour between an rvalue reference and an lvalue reference.

std::string&& rref = std::string("hello");

rref has value category lvalue , and it designates a temporary object. This example is very similar to the previous one, except the temporary object is non-const this time.

Another example:

std::string s1("hello");
std::string&& rref = std::move(s1);
std::string& lref = s1;

In this case, rref is an lvalue, and it designates a non-temporary object. Further, lref and rref (and even s1!) are all indistinguishable from hereon in, except for specifically the result of decltype.

like image 154
M.M Avatar answered Oct 24 '22 07:10

M.M