Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

r-value parameters in a function

Tags:

I was wondering about a c++ behaviour when an r-value is passed among functions.

Look at this simple code:

#include <string>

void foo(std::string&& str) {
  // Accept a rvalue of str
}

void bar(std::string&& str) {
  // foo(str);          // Does not compile. Compiler says cannot bind lvalue into rvalue.
  foo(std::move(str));  // It feels like a re-casting into a r-value?
}

int main(int argc, char *argv[]) {
  bar(std::string("c++_rvalue"));
  return 0;
}

I know when I'm inside bar function I need to use move function in order to invoke foo function. My question now is why?

When I'm inside the bar function the variable str should already be an r-value, but the compiler acts like it is a l-value.

Can somebody quote some reference to the standard about this behaviour? Thanks!

like image 359
BiagioF Avatar asked Aug 12 '16 21:08

BiagioF


People also ask

When should a function take rvalue reference?

rvalue references are more often used as function parameters. This is most useful for function overloads when you want to have different behavior for lvalue and rvalue arguments. Rule 1: Do not write && to return type of a function, and there is no need to return a local variable using std::move .

What is R value Referene in C ++ 11?

“l-value” refers to a memory location that identifies an object. “r-value” refers to the data value that is stored at some address in memory. References in C++ are nothing but the alternative to the already existing variable. They are declared using the '&' before the name of the variable.

What is an R value reference?

Rvalue references is a small technical extension to the C++ language. Rvalue references allow programmers to avoid logically unnecessary copying and to provide perfect forwarding functions. They are primarily meant to aid in the design of higer performance and more robust libraries.

Can a function return an rvalue?

Typically rvalues are temporary objects that exist on the stack as the result of a function call or other operation. Returning a value from a function will turn that value into an rvalue. Once you call return on an object, the name of the object does not exist anymore (it goes out of scope), so it becomes an rvalue.


1 Answers

str is a rvalue reference, i.e. it is a reference only to rvalues. But it is still a reference, which is a lvalue. You can use str as a variable, which also implies that it is an lvalue, not a temporary rvalue.

An lvalue is, according to §3.10.1.1:

An lvalue (so called, historically, because lvalues could appear on the left-hand side of an assignment expression) designates a function or an object. [ Example: If E is an expression of pointer type, then *E is an lvalue expression referring to the object or function to which E points. As another example, the result of calling a function whose return type is an lvalue reference is an lvalue. —end example ]

And an rvalue is, according to §3.10.1.4:

An rvalue (so called, historically, because rvalues could appear on the right-hand side of an assignment expression) is an xvalue, a temporary object (12.2) or subobject thereof, or a value that is not associated with an object.

Based on this, str is not a temporary object, and it is associated with an object (with the object called str), and so it is not an rvalue.

The example for the lvalue uses a pointer, but it is the same thing for references, and naturally for rvalue references (which are only a special type of references).

So, in your example, str is an lvalue, so you have to std::move it to call foo (which only accepts rvalues, not lvalues).

like image 119
Rakete1111 Avatar answered Sep 22 '22 13:09

Rakete1111