C++ 中的局部变量是右值吗?

Are local variables rvalues in C++?

我正在阅读 Stroustrup 的教科书以了解右值和移动构造函数的概念:

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.

上面引用的代码如下所列。

问题:局部变量 res 可以合法地出现在赋值的左侧,例如 res=nullptr。为什么它被视为右值呢?

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;

}

不,局部变量不是右值。在您的示例中,右值是函数返回的临时对象,它是 res 的副本(尽管可以省略复制构造函数或移动构造函数的调用)。

res 本身是函数内的左值。

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

这是错误的。 res 是左值的一个典型例子。我有点担心你的教科书。我们没有太多的上下文,所以这可能只是一个拼写错误或误导性措辞的例子。但是,如果这是一个真正的错误,则表明作者严重缺乏该语言的基础知识。

通常的经验法则是:“如果它有名字,它就不能是右值。如果它没有名字,它很可能是一个右值。”这很有效,即使在一开始看起来令人困惑的情况下也是如此。例如:

// 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)
{
    // ...
}

该规则也适用于您的代码段中的所有位置:

  • 所有 .size() return 值:无名称 -> 右值
  • abresi 有名称 -> 不是右值
  • i!=a.size() 布尔值:无名称 -> 右值
  • a[i]+b[i] 临时:无名称 -> 右值

只有函数的 return 值比较棘手,因为 return 值优化 (RVO) 在这里发挥作用。这里的经验法则是:“如果你 return 一个局部变量,通常不需要 std::move() 它。”