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
?如果rhs
是rvalue
,为什么rhs.m_inner
也不是rvalue
?
答案 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()
来电。