简体   繁体   中英

Are local variables rvalues in C++?

I am reading a textbook from Stroustrup to understand the concept of rvalue and move constructors:

an rvalue is – to a first approximation – a value that you can't assign to, such as an integer returned by a function call, and an rvalue reference is a reference to something that nobody else can assign to. The res local variable in operator+() for Vectors is an example.

The code referred to in the quote above is listed below.

Question: the local variable res can legally appear on the left hand side of an assignment, such as in res=nullptr . Why is it seen as an rvalue instead?

Vector operator+(const Vector& a, const Vector& b) {

  if (a.size()!=b.size()) throw Vector_size_mismatch{};

  Vector res(a.size()); 

  for (int i=0; i!=a.size(); ++i) res[i]=a[i]+b[i]; 

  return res;

}

No, local variables are not rvalues. In your example the rvalue is the temporary object that is a copy of res (though a call of the copy constructor or move constructor can be elided) returned by the function.

res itself is an lvalue within the function.

The res local variable in operator+() for Vectors is an example.

This is wrong. res is rather a prime example of an lvalue. I'm a bit concerned about your textbook. We don't have a lot of context, so this could just be an instance of a typo or misleading phrasing. However, if it is a genuine mistake it shows the author's major lack of knowledge about the fundamentals of the language.

The usual rule of thumb is: “If it has name it cannot be an rvalue. If it doesn't have a name it is likely to be an rvalue.” This works well, even in cases that might seem confusing at first. For example:

// A temporary has no name.
// Therefore: Can call foo() with it.
foo(Object());

void foo(Object&& o)
{
    // o has a name. Therefore: not an rvalue.
    // Therefore: Must move.
    bar(std::move(o));
}

void bar(Object&& o)
{
    // ...
}

The rule also works everywhere in your code snippet:

  • all the .size() return values: no name -> rvalue
  • a , b , res , i have names -> not rvalues
  • the i!=a.size() boolean: no name -> rvalue
  • the a[i]+b[i] temporary: no name -> rvalue

Only the function's return value is more tricky because return value optimization (RVO) plays a role here. The rule of thumb here is: “If you return a local variable there's usually no need to std::move() it.”

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM