目录
to_string传值返回,string类的拷贝构造 vs 移动构造
to_string传值返回,string类的拷贝赋值 vs 移动赋值
一、左值,左值引用,右值,右值引用的相关概念:
1. 什么是左值,什么是左值引用?
左值是一个表示数据的表达式(如变量名或解引用的指针),左值的特征是可以获取它的地址 + 可以对它赋值,左值可以出现在赋值符号的左边。(右值不能出现在赋值符号的左边)。
有一个例外:const修饰的左值不能出现在赋值符号左边。
故,左值最大的特点是是:可以对它取地址。
左值引用就是对左值的引用,给左值取别名。
// 以下的p,b,c,*p都是左值
int* p = new int(0);
int b = 1;
const int c = 2;
*p = 10;
// 左值引用:
int*& rp = p;
int& rb = b;
const int& rc = c;
int& ri = *p;
2. 什么是右值,什么是右值引用?
右值也是一个表示数据的表达式,如:字面常量、表达式返回值,函数返回值(这个不能是左值引 用返回,也就是必须是值返回)...
右值不能出现在赋值符号的左边,可以出现在赋值符号的右边,右值不能取地址。
右值引用就是对右值的引用,给右值取别名。
赋值运算符的左侧必须为左值。“=”: 左操作数必须为左值。
右值可以分为两种:1. 内置类型右值-纯右值 2. 自定义类型右值-将亡值
double x = 10.1, y = 20.2;
// 右值示例:
10;
x+y;
fmin(x, y); // 值返回
// 右值引用示例:
int&& ri = 10;
double&& rd = x + y;
double&& rd2 = fmin(x, y);
3. 右值的属性是右值,右值引用的属性是左值
右值不能取地址,比如10不能取地址。但是右值引用可以取地址,且可以给右值引用赋值。也就是 int&& ri = 10; &ri; ri = 20; 是合法的。因为给右值取别名后,会导致右值引用被存储在特定位置,属性变为左值。
右值引用的属性是左值。const 右值引用的属性是const 左值。因为左值可以取地址,可以赋值。因此右值引用可以取地址,可以赋值。const 右值引用可以取地址,不能赋值。
4. 左值引用与右值引用的简单比较:
1. 左值引用只能引用左值,不能引用右值。 const 左值引用既能引用左值,也能引用右值。
2. 右值引用只能引用右值,不能引用左值。 但是右值引用可以引用move后的左值。(这个其实就是move函数的作用,std::move函数可以将左值强制转化为右值引用,返回这个左值的右值引用)
二、右值引用的作用(使用场景)
既然左值引用可以引用左值,且const 左值引用还可以引用右值,那么右值引用的作用是什么呢?探究C++11引入右值引用的作用之前,先来探究左值引用的作用,以及左值引用的短板,从而理解右值引用的作用。
左值引用的作用:
1. 左值引用做函数参数。
a. 引用传参,减少拷贝,提高效率。最典型的比如拷贝构造函数,operator&