有了左值引用为什么还需要右值引用?
在平时编码过程为了减少数据的拷贝,提高性能,我们一般通过引用的方式来传递参数,例如:
void func(const int &a){
}
int main() {
func(10); // 可以
int a = 20;
func(a); // 可以
return 0;
}
如果在上面的程序中我们将函数func
中的const
修饰去掉之后呢?我们发现调用func(10);
居然无法通过了,这是为什么呢?
在C++中带const修饰的引用成为常量左值引用,常量左值引用是可以绑定右值的,如果去掉了const修饰的话,就不是常量左值引用了,就不能绑定右值了,
func(10);
也就编译是失败了,因为在不带const修饰的函数func
中表明引用a是可以修改的,但是func(10);
传递进去的10确实不可修改的,这就产生了矛盾,也就无法通过编译了。
面对这种情况,右值引用的作用就发挥出来了。
右值引用是 C++11 引入的与 Lambda 表达式齐名的重要特性之一。它的引入解决了 C++ 中大量的历史遗留问题,消除了诸如 std::vector、std::string 之类的额外开销。
什么是右值
那么什么是右值呢?
按照我们以往的编程经验,一般认为位于等号左边的值就是左值,位于等号右边的值就是右值,然而真相并不是这样的。
int a = 10;
int b = a;
例如在异常的代码中如果认为位于表达式左边的值就是左值,位于表达式右边的值就是右值的话,那么在第一行代码中变量a是左值,在第二行代码中变量a却变成了右值,
显然这是矛盾的。那么到底该如何区分左值和右值呢?
在C++ Primer中对左值和右值的归纳为:
当一个对象被用作右值的时候,用的是对象的值(内容);当对象被用作左值的时候,用的是对象的身份(在内存中的位置)。
大概的意思就是说左值就有内存地址的,存活的生命周期较长的,而右值一般是无法获取到内存地址的,生命周期是短暂的。还是以以上的代码为例子,
变量a和变量b都是可以通过取地址符号&
获取到具体的内存地址的,所以变量a和变量b都是左值,而10,是一个普通的字面量,是不可以通过取地址符号&
获取到具体的内存地址的&#