C++11新引入了右值引用的概念。函数
本质上来讲,左值就是在内存中能够寻址的对象(表现形式是能够经过&操做符取指),而右值是在寄存器中或者内存中的匿名对象。对象
左值能够存在赋值运算符左右两边,但右值只能存在赋值运算符右边(这有个例外,当一个类对象重载了负值运算符时,该类对象做为右值也能够存在赋值运算符左边)。好比,生命周期
int a = 0; // a是左值内存
2 = a; // error, 2是匿名对象,是右值,不能放在赋值运算符左边class
a++ = 5; // error,a++表达式返回的是直接数0,是个匿名对象,不能做为左值,只能做为右值语法
++a = 6; // ok, ++a表达式返回的是对象a,所以能够做为左值(这点C++和传统C语言有所不一样)引用
引用是对象的别名,引用分为左值引用和右值引用。引用在声明时就须要被赋值。error
左值引用是对左值对象的引用,而且只能引用左值;而右值引用是对右值的引用,而且只能引用右值。一个右值表达式对象一般在表达式结束时即销毁,而右值表达式被右值引用时,会延长右值表达式对象的生命周期,直到右值引用结束。static
左值引用的语法以下:语言
int a = 10;
int &b = a; // ok,左值引用声明时初始化,引用一个左值表达式。
int &c = 10; // error,左值引用只能引用左值表达式,不能引用右值表达式。
右值引用的语法以下:
int a = 10;
int &&b = a; // error, 右值引用只能引用右值表达式,不能引用左值表达式。
int &&c = 10; // ok
这里有个须要注意的是:普通函数和类静态成员函数的函数名既是左值,也是右值(即,函数名既能够赋值给左值引用,也能够赋值给右值引用)。以下:
void hello() {
std::cout << "hello" << std::endl;
}
class CallBack {
public:
CallBack();
virtual ~CallBack();
static void staticDump() {
std::cout << "staticDump" << std::endl;
}
};
int main() {
typedef void(FuncType)();
typedef void(FuncType1)(CallBack *);
FuncType &func = hello; // 普通函数hello函数名能够做为左值
FuncType &&func1 = hello; // 普通函数hello函数名能够做为右值
func();
func1();
FuncType &funcStatic = CallBack::staticDump; // 类静态成员函数staticDump函数名能够做为左值
FuncType &&funcStatic1 = CallBack::staticDump; // 类静态成员函数staticDump函数名能够做为右值
funcStatic();
funcStatic1();
return 0;
}
这里,更进一步:函数名取地址是右值:
void func() {
std::cout << "func" << std::endl;
}
typedef void (FuncType)();
typedef void (*FuncType1)();
int main() {
int a = 10;
FuncType &f1 = func;
FuncType &&f2 = func;
f1();
f2();
FuncType1 &f3 = &func; // 错误,&func是右值,不能赋值给左值引用
FuncType1 &&f4 = &func; // ok, &func是右值,能够赋值给右值引用
f4();
return 0; } 最后,不管是左值引用,右值引用函数名 或者 函数地址,均可以经过引用调用函数。