类,Rvalues和Rvalue引用

左值是绑定到存储器的确定区域的值,而右值是表达式值,其存在是临时的,并且不一定是指存储器的确定区域。只要在预期rvalue的位置使用左值,编译器就会执行左值到右值的转换,然后继续进行求值。 http://www.eetimes.com/discussion/programming-pointers/4023341/Lvalues-and-Rvalues 每当我们构造一个临时(匿名)类对象或从函数返回一个临时类对象时,虽然该对象是临时的,但它是可寻址的。但是,对象仍然是有效的右值。这意味着当编译器期望使用左值时,对象是a)可寻址的右值或b)从左值隐式转换为右值。 例如:
class A
{
public:
    int x;
    A(int a) { x = a; std::cout << "int conversion ctorn"; }
    A(A&) { std::cout << "lvalue copy ctorn"; }
    A(A&&) { std::cout << "rvalue copy ctorn"; }
};
A ret_a(A a) 
{
    return a;
}

int main(void)
{
    &A(5); // A(5) is an addressable object
    A&& rvalue = A(5); // A(5) is also an rvalue
}
我们还知道函数返回的临时对象(在下面的例子中是
a
)是lvalues作为这个代码段:
int main(void)
{
    ret_a(A(5));
}
产生以下输出:
int conversion ctor
lvalue copy ctor
表示使用实际参数
A(5)
调用函数
ret_a
调用转换构造函数
A::A(int)
,它构造函数的形式参数
a
,其值为5。 当函数完成执行时,它然后使用
a
作为其参数构造一个临时的
A
对象,该对象调用
A::A(A&)
。但是,如果我们要从重载构造函数列表中删除
A::A(A&)
,则返回的临时对象仍将匹配rvalue-reference构造函数
A::A(A&&)
。 这是我不太了解的:对象
a
如何匹配右值引用和左值引用?显然
A::A(A&)
A::A(A&&)
更好(因此
a
必须是左值)。但是,因为rvalue引用不能初始化为左值,假定形式参数
a
是左值,它应该不能匹配对
A::A(A&&)
的调用。如果编译器正在进行左值到右值的转换,那将是微不足道的。从'A'转换为'A&amp;'的事实也是微不足道的,两个函数都应该具有相同的隐式转换序列,因此,当
A::A(A&)
A::A(A&&)
都在重载函数候选集中时,编译器不应该推导出最佳匹配函数。 而且,我之前提出的问题是: 给定对象如何匹配右值引用和左值引用?     
已邀请:
为了我:
int main(void)
{
    ret_a(A(5));
}
产量:
int conversion ctor
rvalue copy ctor
(即右值,而不是左值)。这是编译器中的错误。然而,这是可以理解的,因为这种行为的规则仅在几个月前(2010年11月)发生了变化。更多关于此的信息。   当函数完成执行时,   然后构建一个临时的
A
  使用
a
作为其参数的对象   调用
A::A(A&)
。 其实没有。当函数
ret_a
完成执行时,它会使用
a
作为参数构造一个临时的
A
对象,该对象调用
A:A(A&&)
。这是由于[class.copy] / p33] 1:   当一个省的标准   复制操作已满足或将被满足   除了源的事实   object是一个函数参数,和   指定要复制的对象   通过左值,重载决议来   选择副本的构造函数是   首先表现就像对象一样   由右值指定。如果过载   分辨率失败,或者类型如何   所选的第一个参数   构造函数不是右值引用   到对象的类型(可能   cv-qualified),重载分辨率是   再考虑一下   对象作为左值。 [注意:这个   必须进行两级重载分辨率   无论是否复制都执行   将会出现这种情况。它决定了   如果省略则调用构造函数   未执行,并且已选中   即使构造函数必须是可访问的   电话被忽略了。 - 结束说明] 但是,如果删除
A::A(A&&)
构造函数,则将选择
A::A(&)
作为返回。虽然在这种情况下,然后参数
a
的构造将失败,因为您无法使用rvalue构造它。无论如何忽略这一点,我相信你的最终问题是:   给定对象如何匹配两者   右值参考和左值   参考? 在提到声明时:
return a;
答案在草案标准的上述段落中:首先尝试重载决策,好像
a
是一个右值。如果失败,则使用
a
作为左值再次尝试重载决策。仅在允许复制省略的情况下(例如返回声明)尝试这两个阶段的过程。 最近刚更改了C ++ 0x草案,以便在返回按值传递的参数时允许两阶段重载解析过程(如示例所示)。这就是我们所看到的不同编译器行为的变化的原因。     

要回复问题请先登录注册