C++11 为什么rhs.m_内部是左值而不是右值?

C++11 为什么rhs.m_内部是左值而不是右值?,c++11,visual-studio-2013,move-semantics,C++11,Visual Studio 2013,Move Semantics,为什么rhs.m_inner在这种情况下是levalue?如果rhs是一个rvalue,为什么rhs.m_inner不是一个rvalue?如果rhs是一个rvalue,那么rhs.m_inner也会是一个rvalue。但是,rhs是一个命名变量(无论它是右值引用),因此它是一个左值源文本rhs在这里指的是两个不同的东西: 变量rhs,对外部对象的右值引用。此变量的类型为外部&& 计算该变量值的表达式rhs。此表达式具有类型outer和值类别lvalue 引用变量的左值/右值决定了引用可以绑定

为什么
rhs.m_inner
在这种情况下是
levalue
?如果
rhs
是一个
rvalue
,为什么
rhs.m_inner
不是一个
rvalue

如果
rhs
是一个rvalue,那么
rhs.m_inner
也会是一个rvalue。但是,
rhs
是一个命名变量(无论它是右值引用),因此它是一个
左值
源文本
rhs
在这里指的是两个不同的东西:

  • 变量
    rhs
    ,对
    外部
    对象的右值引用。此变量的类型为
    外部&&
  • 计算该变量值的表达式
    rhs
    。此表达式具有类型
    outer
    和值类别
    lvalue
引用变量的左值/右值决定了引用可以绑定到哪些表达式的值类别,它对计算变量的表达式的值类别没有影响。对引用求值总是导致左值。

对于引用,要调用
outer(outer&&rhs)
,可以使用以下代码:

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;
};
它在0处构造类型为outer的匿名对象,在1处构造类型为outer且名称为out的对象。(存在
(外部)
是为了防止
out
表单成为
外部(外部(*)()

看到那个匿名者了吗?现在考虑外部(E&&RHS)的定义:

outer(outer&&rhs):m_-inner(rhs.m_-inner){
outer(outer&&
有一个名为rhs的
outer&
类型的参数。 现在,ex.1中的语句0和第一个参数之间存在明显的区别:前者没有名称,后者有名称,因此消除了对象的匿名性。现在,因为对象有一个名称,所以它只是一个左值引用(它允许人们使用swap习惯用法构造)
当有人需要将其用作右值引用时,问题就出现了。为此

模板
typename std::remove_reference::type&&move(T&&T);
函数已创建。它是干什么的?它(更多关于各种价值观),这正是我们所需要的!因此,最终代码可能是:

#包括
类外部{
班级内部{
公众:
内部(){}
内部(内部和右侧){}
};
公众:
外(){}
外部(外部和右侧):内部(std::move(rhs.m_-inner)){}
私人:
内m_内;
};

注意
#include
std::move()
调用。

这里似乎有两个独立的问题。第一个问题是“为什么不使用move构造函数,除非我键入
std::move
?”。第二个问题是“为什么我的类有一个复制构造函数?”。它们是独立的问题,不是真正相关的,如果你可以编辑你的问题,只关注其中一个,可能会更好。对于你的第一个问题:对于你的第二个问题,基本上已经回答了,让复制构造函数禁用隐式移动构造函数,但不是相反。好的,是的,这个链接确实解释了答案。这可能是另一个重复:)@Mordachai这是与
移动相关的最令人困惑的话题之一。这就是说,真棒在《进入会员》一节中完美地回答了这个问题。这个问题很可怕,但同时又很可怕,因为它可能应该被拆分,它太全面了,你很容易忽略你正在寻找的特定部分。彻底地。
outer out((outer)outer()/*0*/)/*1*/;