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*/;