一、关于lvalue和rvalue
lvalue是指一块内存且我们可以用&符号取其地址的一个"引用"; rvalue是不能对其进行'&'操作的一个"引用"。 常见的rvalue有哪些呢?比如const int a=2; const ra&=a; 按值传递的函数参数、函数按值返回值产生的临时对象。
二、关于临时对象
临时对象有如下特征:1.没有名字;2.存在时间短;3.只能做rvalue;4.跟const修饰的变量性质很像。
三、关于c++03中的rvalue
通常情况下,我们用引用来作为参数以避免临时变量的产生。
3.1 但rvalue这种引用是不能直接传递给一个"没有const修饰的引用形参",也就是说rvalue只能传给带const修饰的函数形参。
3.2 当rvalue正确地被传递给一个带const修饰的形参时,会产生一个新的临时对象,它的生命周期很短,只函数结束时结束。
3.3 在新的c++中(c++11),引入了rvalue"引用",用两个'&'符号表示: class node{}; void func(node&& obj){ } 这种rvalue有两个功能:
3.3.1 move语义
3.3.2 模板中forward语义
3.4 const
常引用: const T&
常函数: void func() const
临时变量没有绑定 非-常引用
但非常函数可接受临时变量作参数
四、一些代码
template <class T>
class clone_ptr
{
private:
T* ptr;
public:
explicit clone_ptr(T* p = 0) : ptr(p) {
cout<<"构造clone"<<this<<endl;
}
~clone_ptr() {delete ptr;cout<<"析构"<<this<<endl;}
private:
//non-const copy semantics 代码1
clone_ptr( clone_ptr& p): ptr(p.ptr ? p.ptr->clone() : 0){
cout<<"非常语义copy构造"<<this<<endl;
}
clone_ptr& operator=( clone_ptr& p){
cout<<"非常语义赋值"<<this<<endl;
return *this;
}
public:
//const copy semantics 代码2
clone_ptr(const clone_ptr& p)
: ptr(p.ptr ? p.ptr->clone() : 0){
cout<<"拷贝语义copy构造"<<this<<endl;
}
clone_ptr& operator=(const clone_ptr& p) {
cout<<"拷贝语义赋值"<<this<<endl;
if (this != &p){
delete ptr;
ptr = p.ptr ? p.ptr->clone() : 0;
}
return *this;
}
// move semantics
clone_ptr(clone_ptr&& p):ptr(p.ptr) {
cout<<"移动语义构造函数"<<this<<endl;
p.ptr = 0;
}
clone_ptr& operator=(clone_ptr&& p){
cout<<"移动语义赋值函数"<<this<<endl;
std::swap(ptr, p.ptr);
return *this;
}
// Other operations
T& operator*() const {return *ptr;}
// ...
};
有以下测试函数:
clone_ptr<node> func()
{
return clone_ptr<node> (new node(0));
}
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
clone_ptr<node> p1(new node(0));
clone_ptr<node> p2(p1);//lvalue
cout<<"======================================="<<endl;
clone_ptr<node> p3=func();//rvalue
system("pause");
return 0;
}
结果是这样的:
lvalue部分测试代码:
三种函数都存在的情况下,会优先匹配non-const拷贝构造/赋值函数
如果non-const存在但私有,编译会报错。
出果non-const使用默认的,则会调用const 型;在没有non-const拷贝构造函数的情况下,const再私有的话,也会报错,说明const是lvalue考虑的第二顺序函数。
总结就是 对lvalue: non-const ->const->默认non-const->且不会调用 rvalue&&,因为它是lvalue
rvalue部分测试代码:会优先匹配移动语义的rvalue ref 构造/赋值函数
三种都有的话,匹配non-const
若non-const存在但私有的话,匹配默认rvalue ref
若rvalue ref 私有,则编译报错
若non-const私有或默认,则优先调用rvalue ref, 此时若rvalue ref不存在,则匹配 const
rvalue匹配顺序 non-const->rvalue ref->const
五、参考
http://en.wikipedia.org/wiki/C%2B%2B11#Rvalue_references_and_move_constructors
In C++03 (and before), temporaries (termed "rvalues", as they often lie on the right side of an assignment) were intended to never be modifiable — just as in C — and were considered to be indistinguishable from const T&
types; nevertheless, in some cases, temporaries could have been modified, a behavior that was even considered to be a useful loophole (for the former, see [7]). C++11 adds a new non-const reference type called an rvalue reference, identified by T&&
. This refers to temporaries that are permitted to be modified after they are initialized, for the purpose of allowing "move semantics".
在c++03中(及其以前版本),临时变量(术语叫"rvalues",因为它们常常处于赋值符号'='的右边)被认为从来不会被修改---如在C语言中的语义---并且被认为与 'const T&'(常引用)类型没什么不同;但是,一些情况下,临时变量曾被修改过,一个甚至被认作非常有用的技巧。c++11添加新的 非-常引用 类型,称为 "rvalue 引用",用T&&来表示。它是指那些允许被修改的临时变量,目的是为了实现"move语义"。
所以说,rvalue是一种新的 非-常引用,用来描述可修改的临时变量(临时变量本来是不能修改的)。