No *_*One 13 c++ reference rvalue lvalue rvalue-reference
左值是绑定到存储器的确定区域的值,而右值是表达式值,其存在是临时的,并且不一定是指存储器的确定区域.只要在预期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 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
}
Run Code Online (Sandbox Code Playgroud)
我们还知道函数返回的临时对象(在下面的例子中a)是lvalues作为这个代码段:
int main(void)
{
ret_a(A(5));
}
Run Code Online (Sandbox Code Playgroud)
产生以下输出:
int conversion ctor
lvalue copy ctor
指示ret_a使用实际参数A(5)调用函数会调用转换构造函数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&"转换也是微不足道的事实,这两个函数应具有相同的隐式转换序列行列,因此,编译器不应该能够推断出的最佳匹配函数当两个A::A(A&)和A::A(A&&)是在重载的函数候选人集.
而且,我之前提出的问题是:
给定对象如何匹配右值引用和左值引用?
为了我:
int main(void)
{
ret_a(A(5));
}
Run Code Online (Sandbox Code Playgroud)
产量:
int conversion ctor
rvalue copy ctor
Run Code Online (Sandbox Code Playgroud)
(即右值,而不是左值).这是编译器中的错误.然而,这是可以理解的,因为这种行为的规则仅在几个月前(2010年11月)发生了变化.更多关于此的信息.
当函数完成执行时,它然后
A使用a作为其调用的参数构造临时对象A::A(A&).
其实没有.当函数ret_a完成执行时,它然后A使用a作为其调用的参数构造临时对象A:A(A&&).这是由于[class.copy]/p33] 1:
当满足或将满足复制操作的省略标准时,除了源对象是函数参数这一事实,并且要复制的对象由左值指定,重载决策选择复制的构造函数是首先执行,好像对象是由右值指定的.如果重载决策失败,或者所选构造函数的第一个参数的类型不是对象类型的rvalue引用(可能是cv-qualified),则再次执行重载决策,将对象视为左值.[注意:无论是否发生复制省略,都必须执行此两阶段重载决策.如果未执行elision,它将确定要调用的构造函数,并且即使调用被省略,也必须可以访问所选的构造函数. - 结束说明]
但是,如果删除A::A(A&&)构造函数,A::A(&)则会选择返回.虽然在这种情况下,然后参数的构造a将失败,因为您无法使用rvalue构造它.无论如何忽略这一点,我相信你的最终问题是:
给定对象如何匹配右值引用和左值引用?
在提到声明时:
return a;
Run Code Online (Sandbox Code Playgroud)
答案在标准草案的上述段落中:首先尝试重载解析,就好像a是一个右值.如果失败,则使用a左值再次尝试重载决策.仅在允许复制省略的情况下(例如返回声明)尝试这两个阶段的过程.
最近刚更改了C++ 0x草案,以便在返回按值传递的参数时允许两阶段重载解析过程(如示例所示).这就是我们所看到的不同编译器行为的变化的原因.
| 归档时间: |
|
| 查看次数: |
2080 次 |
| 最近记录: |