lvalue是一个绑定到一定内存区域的值,rvalue是一个表达式值,它的存在是暂时的,并且不一定是指确定的记忆区域。每当在期望rvalue的位置使用lvalue时,编译器将执行lvalue到rvalue的转换,然后继续进行计算。
http://www.eetimes.com/discussion/programming-pointers/4023341/Lvalues-and-Rvalues
每当我们构造一个临时(匿名)类对象或从函数返回一个临时类对象时,尽管该对象是临时的,但它是可寻址的。但是,对象仍然是一个有效的rvalue。这意味着当编译器期望使用lvalue时,对象是a)可寻址的rvalue或b)被隐式地从lvalue转换为rvalue。
例如:
class A
{
public:
int x;
A(int a) { x = a; std::cout << "int conversion ctor\n"; }
A(A&) { std::cout << "lvalue copy ctor\n"; }
A(A&&) { std::cout << "rvalue copy ctor\n"; }
};
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)是lvalue,因为这个代码段:
int main(void)
{
ret_a(A(5));
}产生以下输出:
int conversion ctor
lvalue copy ctor
指示使用实际参数ret_a调用函数A(5)调用转换构造函数A::A(int),该构造函数用值5构造函数的形式参数a。
当函数完成执行时,它使用a作为参数构造一个临时a对象,该参数调用A::A(A&)。但是,如果要从重载构造函数列表中删除A::A(A&),则返回的临时对象仍将与rvalue-引用构造函数A::A(A&&)匹配。
这就是我不太理解的:对象a如何匹配rvalue引用和lvalue引用?显然,A::A(A&)比A::A(A&&)更匹配(因此a必须是一个lvalue)。但是,由于rvalue引用不能初始化为lvalue,因此,考虑到形式参数a是lvalue,它不应该能够匹配对A::A(A&&)的调用。如果编译器正在进行从lvalue到rvalue的转换,这将是微不足道的。从'A‘到'A&’的转换也很简单,这两个函数都应该有相同的隐式转换序列,因此,当A::A(A&)和A::A(A&&)都在重载的函数候选集中时,编译器不应该能够推断出最佳匹配函数。
此外,我以前提出的问题是:
给定的对象如何匹配rvalue引用和lvalue引用?
发布于 2011-03-11 00:36:32
对我来说:
int main(void)
{
ret_a(A(5));
}产量:
int conversion ctor
rvalue copy ctor(即rvalue,而不是lvalue)。这是编译器中的一个bug。然而,这是可以理解的,因为仅仅几个月前(2010年11月),针对这种行为的规则发生了变化。下面会有更多的介绍。
当函数完成执行时,它使用
a作为参数构造一个临时a对象,该参数调用A::A(A&)。
其实没有。当函数ret_a完成执行时,它使用a作为参数构造一个临时A对象,该参数调用A:A(A&&)。这要归功于class.copy/p33]1
如果符合或将满足复制操作的省略条件,除非源对象是函数参数,并且要复制的对象由lvalue指定,则首先执行重载解析,以选择副本的构造函数,就好像对象是由rvalue指定的一样。如果重载解析失败,或者所选构造函数的第一个参数的类型不是对象类型的rvalue引用(可能是cv限定的),则再次执行重载解析,将对象视为lvalue。注意:无论复制是否会发生,这种两阶段过载解决方案都必须执行.如果不执行省略,它将确定要调用的构造函数,即使调用被省略,所选的构造函数也必须是可访问的。-尾注
但是,如果删除A::A(A&&)构造函数,则将选择A::A(&)作为返回。尽管在这种情况下,参数a的构造将失败,因为您不能使用rvalue来构造它。然而,暂时忽略这一点,我相信你的最终问题是:
给定的对象如何匹配rvalue引用和lvalue引用?
在提及该声明时:
return a;答案是在上面引用的标准草案段落中:第一次过载解析被尝试,就好像a是一个rvalue一样。如果失败,将使用a作为lvalue再次尝试重载解析。这个两阶段的过程只在允许复制省略的上下文中尝试(例如返回语句)。
最近对C++0x草案进行了更改,以便在返回通过值传递的参数时允许两阶段过载解析过程(如您的示例中所示)。这就是我们所看到的不同编译器的不同行为的原因。
https://stackoverflow.com/questions/5266783
复制相似问题