虽然不是实际标准,但我依赖 this page在 cppreference.com 上查看此特定措辞:
An lvalue is an expression that identifies a non-temporary object or a non-member function.
The following expressions are lvalues:
- The name of a variable or function in scope, regardless of type, such as std::cin or std::endl. Even if the variable's type is rvalue reference, the expression consisting of its name is an lvalue expression.
...
我对上面引用的部分的(简化)理解是左值:
- 仅供引用
- 不得是临时对象
我知道引用不是对象,因此第 2 点必须意味着就引用而言,它不能引用临时对象。但是,从表达式本身来看,这是否意味着对临时变量的引用不是左值?您可以引用临时和非临时对象:
int myvar = 0;
int& ref_myvar = myvar; // Reference to non-temporary
class foo {};
foo const& ref_foo = foo{}; // Reference to temporary
在上面的代码片段中,稍后在单独的表达式中使用 ref_foo
是否是左值?右值引用有一条规则,规定在表达式中按名称使用的右值引用仍然是左值(因为您引用了此时的名称)。此规则是否也适用于左值引用(因为它们也有名称,并且在表达式中使用名称本身将使其成为左值,就像对右值引用变量一样)?
我希望我说得有道理。至少我希望我的困惑的根源是显而易见的。有关如何在表达式中使用上面的左值引用来证明与我的问题相关的一些观点的一些示例也将有很大的帮助。
最佳答案
我想说,cppreference 措辞对于“一般介绍”级别的讨论,甚至对于“大多数日常用途”级别的讨论来说都是可以的。然而,一旦您了解了精细的技术细节,这样的陈述可能会变得有些误导。
重要的一点是,值类别(“作为左值”)是表达式的属性,而不是对象的属性。您可以拥有一个临时对象通过左值访问,并且可以通过右值访问非临时对象。
引用您的示例:
ref_myvar
和 ref_foo
都是左值,并且始终如此,无论您如何使用它们。具体如下:
foo&& rref = foo{};
rref
也是并且永远都是左值。它是对右值的引用,但引用本身有名称,左值也是如此。
如果您想将左值视为右值,请使用标准提供的大小写运算符:
rvalue = std::move(lvalue);
让我们分析一下这段代码:
int someint = std::move(ref_myvar);
ref_myvar
是一个左值。 std::move(ref_myvar)
是一个右值。 someint
是一个左值。
我认为没有一种简洁的方法可以在不完全标准化的情况下定义左值,但是名称(或缺少名称)在大多数定义中起着重要作用。我将尝试给出这样的定义;这些是左值:
- 作为名称的表达式,枚举器和成员函数除外。
- “对某物的左值引用”类型的表达式。
- 取消引用指针的结果。
请注意,ref_myvar
、ref_foo
和 rref
都是左值,因为它们有名称。 std::move(ref_myvar)
没有名称,因此它是一个右值。
关于c++ - 左值真的是非临时对象吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32054791/