左值是绑定到内存的明确区域的值,而右值是表达式值,其存在是临时的,并不一定引用到明确的内存区域。每当在期望右值的位置使用左值时,编译器执行左值到右值的转换,然后继续评估。
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
}
我们也知道,函数返回的临时对象(在下面的代码段中为
a
)是左值,如下所示:int main(void)
{
ret_a(A(5));
}
产生以下输出:
int转换构造函数
左值复制构造函数
表明使用实际参数A(5)调用函数ret_a时,调用了转换构造函数A::A(int),该构造函数使用值5构造函数的形式参数a。
当函数执行完成后,它将使用a作为其参数构造一个临时的A对象,这将调用A::A(A&)。但是,如果我们从重载构造函数的列表中删除A::A(A&),返回的临时对象仍将匹配rvalue-reference构造函数A::A(A&&)。
这是我不太理解的地方:对象a如何既匹配rvalue引用又匹配lvalue引用?显然,A::A(A&)比A::A(A&&)更匹配(因此a必须是一个lvalue)。但是,由于rvalue引用不能被初始化为lvalue,而形式参数a是lvalue,所以它不应该能够匹配到对A::A(A&&)的调用。如果编译器进行lvalue-to-rvalue转换,那就很容易了。事实上,从'A'到'A&'的转换也很简单,两个函数应该具有相同的隐式转换序列等级,因此当A::A(A&)和A::A(A&&)都在重载函数候选集中时,编译器不应该能够推断出最佳匹配函数。
此外,之前我问过的问题是:
给定的对象如何既匹配rvalue引用又匹配lvalue引用?
a
对象不就被认为是一个表达式吗? - No One