左值是否真的是非临时对象?

时间:2015-08-17 15:59:38

标签: c++ c++11

虽然不是实际标准,但我在cppreference.com上依赖this page来解决这个特定的措辞:

  

左值是一个表达式,用于标识非临时对象或   非会员职能。

     

以下表达式是左值:

     
      
  • 范围内的变量或函数的名称,无论其类型如何,例如std :: cin或std :: endl。即使变量的类型是rvalue   引用,由其名称组成的表达式是左值   表达
  •   
     

...

我(简化)对上面引用部分的理解是左值:

  1. 是参考
  2. 不得为临时对象
  3. 我知道引用不是对象,因此第2点必须表示就引用而言,它不能引用到临时对象。但是,从表达本身来看,这是否意味着对临时的引用不是左值?您可以引用临时非临时对象:

    int myvar = 0;
    int& ref_myvar = myvar; // Reference to non-temporary
    
    class foo {};
    foo const& ref_foo = foo{}; // Reference to temporary
    

    在上面的代码段中,稍后在单独的表达式中使用ref_foo是否是左值? rvalue引用有一个规则,指出在表达式中使用 by name 的rvalue引用仍然是lvalues(因为你在那个位置引用了名称)。此规则是否也适用于左值引用(因为它们也有名称并且在表达式中使用名称本身会使它成为左值,就像对于右值引用变量一样)?

    我希望我有某种意义。至少我希望我的困惑的来源是显而易见的。上面的左值引用如何在表达式中用来证明与我的问题相关的一些点的一些例子也将是一个巨大的帮助。

1 个答案:

答案 0 :(得分:3)

我会说,对于“一般性介绍” - 级别讨论甚至是“大多数日常用途” - 级别讨论,cppreference措辞都可以。但是,一旦你掌握了精细的技术细节,这些陈述就会变得有些误导。

重要的一点是值类别(“是左值”)是表达式的属性,不是对象的属性。你可以拥有一个临时对象通过左值访问,你可以通过右值访问非临时对象。

参考你的例子:

无论您如何使用它们,

ref_myvarref_foo都是左值,而且始终是左值。在以下内容中:

foo&& rref = foo{};

rref也是,也将永远是左值。它是对rvalue的引用,但引用本身有一个名称,因此是一个左值。

如果您想将左值作为右值处理,请使用标准提供的案例运算符:

rvalue = std::move(lvalue);

让我们分析一下这段代码:

int someint = std::move(ref_myvar);

ref_myvar是一个左值。 std::move(ref_myvar)是一个右值。 someint是左值。

我认为没有简洁的方法来定义左值而没有完全标准,但 name (或缺少)在大多数定义中起着重要作用。我会尝试这样的定义;这些是左值:

  • 除枚举器和成员函数外的名称表达式。
  • “对某事物的左值引用”类型的表达。
  • 取消引用指针的结果。

请注意,ref_myvarref_foorref都是左值,因为它们有一个名称。 std::move(ref_myvar)没有名称,因此它是一个右值。