为什么rhs.m_inner是左值而不是右值?

时间:2014-12-08 20:17:47

标签: c++11 visual-studio-2013 move-semantics

class outer
{
  class inner
  {
  public:
    inner() { }
    inner(inner&& rhs);
  }
public:
  outer() { }
  outer(outer&& rhs)
   : m_inner(rhs.m_inner)  // why is rhs.m_inner an lvalue and not an rvalue?
  { }
private:
  inner m_inner;
};

为什么rhs.m_inner在此上下文中为lvalue?如果rhsrvalue,为什么rhs.m_inner也不是rvalue

3 个答案:

答案 0 :(得分:2)

源文本rhs在这里指的是两个不同的东西:

  • 变量 rhs,是outer对象的右值引用。此变量的类型为outer&&
  • 表达式 rhs,用于评估该变量的值。此表达式的类型为outer,值类别为lvalue

引用变量的左值/右值确定引用可以绑定的表达式的值类别,它对评估变量的表达式的值类别没有影响。评估引用始终会产生左值。

答案 1 :(得分:0)

如果rhs是左值,那么rhs.m_inner也是左值。但是,rhs是一个命名变量(并不意味着它是一个右值参考),所以它是lvalue

答案 2 :(得分:0)

参考C++ Annotations,要拨打outer(outer&& rhs),可以使用以下代码:

outer out((outer)outer()/*0*/)/*1*/;

在0处构造一个类型为outer的匿名对象,在1处它构造一个名为out 的外部类型的对象。 ((outer)用于阻止out表单成为outer(outer (*)())

请参阅匿名吗?现在考虑外部(外部&& rhs)的定义:

outer(outer && rhs) : m_inner(rhs.m_inner) {}

outer(outer &&)有一个类型为outer && 的参数名为rhs 。 现在,ex中的语句0之间存在可感知的差异。 1和第一个参数:前者没有名字,后者有,因此删除了对象的 anonimity 。现在,由于该对象具有名称,它只是一个左值引用(允许人们使用逐个构造的习惯用法)。
但是,当有人需要将它用作右值参考时,问题就出现了。为此

template<class T>
typename std::remove_reference<T>::type&& move(T&& t);

功能已创建。它有什么作用?它"obtains an rvalue reference to its argument and converts it to an xvalue"(更多关于各种值here),这正是我们所需要的!所以,最终的代码可能是:

#include <utility>

class outer {
  class inner {
    public:
      inner() {}
      inner(inner && rhs) {}
  };

  public:
    outer() {}
    outer(outer && rhs) : m_inner(std::move(rhs.m_inner)) {}

  private:
    inner m_inner;
};

请注意#include <utility>std::move()来电。