【深入理解C++】左值引用、常引用、右值引用、std::move()函数
创始人
2024-01-30 22:10:10
0

文章目录

  • 1.左值引用
  • 2.常引用
    • 2.1 const引用可以指向临时数据
    • 2.2 const引用可以指向不同类型的数据
    • 2.3 const引用作为函数参数
  • 3.右值引用
  • 4.std::move()函数

1.左值引用

左值引用只能绑定到左值上,不能绑定到右值上。

左值引用不能绑定到临时变量上,因为临时变量被系统当作右值。

所有变量都是左值,因为它们是有地址的。

任何函数里边的形参都是左值。

#include 
using namespace std;int main()
{int& ref1 = 20; // 错误,左值引用不能绑定到右值上int a = 10, b = 20;int& ref2 = a; // 正确,左值引用能绑定到左值上	int& ref3 = a + b; // 错误,左值引用不能绑定到右值上return 0;
}

返回左值引用的函数、赋值运算符、下标运算符、解引用运算符、前置递增运算符、前置递减运算符等,返回的都是左值,可以将左值引用绑定到这类表达式的结果上。

#include 
using namespace std;int main()
{int i = 10;int& ref = ++i; // 左值引用可以绑定到左值上,ref就变成了i的别名i += 5;cout << i << endl; // 16cout << ref << endl; // 16return 0;
}

2.常引用

引用可以被 const 修饰,这样就无法通过引用修改数据了,称为常引用。const 必须写在 & 符号的左边,才能算是常引用。

引用 int &p 相当于 int* const p,常引用 const int &p 相当于 const int* const p

#include 
using namespace std;int main() {int height = 20;int age = 10;// p1不能修改指向,但是可以利用p1间接修改所指向的变量int* const p1 = &age;//p1 = &height; // 报错*p1 = 30;cout << age << endl; // 30// ref1不能修改指向,但是可以通过ref1间接修改所指向的变量int & const ref1 = age;ref1 = 40;cout << age << endl; // 40// p2可以修改指向,但是不可以利用p2间接修改所指向的变量int const* p2 = &age;p2 = &height;//*p2 = 30; // 报错// ref2不能修改指向,也不可以通过ref2间接修改所指向的变量int const &ref2 = age; // 常引用//ref2 = 40; // 报错return 0;
}

2.1 const引用可以指向临时数据

举例1:const引用指向常量

#include 
using namespace std;int main() {const int &ref = 30;return 0;
}

举例2:const引用指向表达式

#include 
using namespace std;int main() {int a = 1;int b = 2;const int &ref = a + b;return 0;
}

举例3:const引用指向函数返回值

#include 
using namespace std;int func() {return 8;
}int main() {const int &ref = func();return 0;
}

2.2 const引用可以指向不同类型的数据

#include 
using namespace std;int main() {int age = 10;const double &ref = age;return 0;
}

当常引用指向了不同类型的数据时,会产生临时变量,即引用指向的并不是初始化时的那个变量。

举例1:查看常引用指向相同类型数据的汇编代码

#include 
using namespace std;int main() {int age = 10;const int &ref = age;age = 30;cout << age << endl; // 30cout << ref << endl; // 30return 0;
}

在这里插入图片描述

举例2:查看常引用指向不同类型数据的汇编代码

#include 
using namespace std;int main() {int age = 10;const long &ref = age;age = 30;cout << age << endl; // 30cout << ref << endl; // 10return 0;
}

在这里插入图片描述

2.3 const引用作为函数参数

const引用作为函数参数时,可以接受const和非const实参。

非const引用作为函数参数时,只能接受非const实参。

const引用跟非const引用可以构成函数重载。

const引用作为函数参数时的上述规则也适用于const指针。

#include 
using namespace std;int sum(int &v1, int &v2) {cout << "sum(int &v1, int &v2)" << endl;return v1 + v2;
}int sum(const int &v1, const int &v2) {cout << "sum(const int &v1, const int &v2)" << endl;return v1 + v2;
}int main() {// 非const实参int a = 10;int b = 20;sum(a, b);// const实参const int c = 10;const int d = 20;sum(c, d);sum(10, 20);return 0;
}

输出结果如下:

在这里插入图片描述

3.右值引用

右值引用只能绑定到右值上,不能绑定到左值上。右值引用通常绑定到一些即将销毁的或一些临时的对象上。

#include 
using namespace std;int main()
{int&& ref1 = 10; // 正确,右值引用能绑定到右值上int a = 100, b = 200;int&& ref2 = a; // 错误,右值引用不能绑定到左值上int&& ref3 = a * b; // 正确,右值引用能绑定到右值上return 0;
}

返回非引用类型的函数、算术运算符、关系运算符、位运算符、后置递增运算符、后置递减运算符等,返回的都是右值,不能将左值引用绑定到这类表达式上,可以将常引用或右值引用绑定到这类表达式上。

#include 
using namespace std;int main()
{int i = 10;int&& ref = i++; // 右值引用绑定到临时变量上,此后ref和i没有关系i += 5;cout << i << endl; // 16cout << ref << endl; // 10return 0;
}

4.std::move()函数

std::move() 的能力只有一个:把一个左值强制转换成一个右值。实际上这个函数根本就没有做移动的操作。

#include 
using namespace std;int main()
{int i = 10;int&& ref = std::move(i); // 把一个左值强制转换成一个右值i = 20;cout << i << endl; // 20cout << ref << endl; // 20return 0;
}
#include 
using namespace std;int main()
{int&& ref1 = 100;int&& ref2 = std::move(ref1); // 把一个左值强制转换成一个右值ref1 = 200;cout << ref1 << endl; // 200cout << ref2 << endl; // 200return 0;
}
#include 
using namespace std;int main()
{string src = "I love China!";string dst = std::move(src); // string里的移动构造函数把src的内容转移到dst中去了,而不是std::move()转移的cout << "&src = " << &src << ", src = " << src << endl;cout << "&dst = " << &dst << ", dst = " << dst << endl;return 0;
}

输出结果如下:

在这里插入图片描述

#include 
using namespace std;int main()
{string src = "I love China!";string&& ref = std::move(src); // 把一个左值强制转换成一个右值cout << "&src = " << &src << ", src = " << src << endl;cout << "&dst = " << &ref << ", dst = " << ref << endl;return 0;
}

输出结果如下:

在这里插入图片描述

相关内容

热门资讯

喜欢穿一身黑的男生性格(喜欢穿... 今天百科达人给各位分享喜欢穿一身黑的男生性格的知识,其中也会对喜欢穿一身黑衣服的男人人好相处吗进行解...
发春是什么意思(思春和发春是什... 本篇文章极速百科给大家谈谈发春是什么意思,以及思春和发春是什么意思对应的知识点,希望对各位有所帮助,...
网络用语zl是什么意思(zl是... 今天给各位分享网络用语zl是什么意思的知识,其中也会对zl是啥意思是什么网络用语进行解释,如果能碰巧...
为什么酷狗音乐自己唱的歌不能下... 本篇文章极速百科小编给大家谈谈为什么酷狗音乐自己唱的歌不能下载到本地?,以及为什么酷狗下载的歌曲不是...
华为下载未安装的文件去哪找(华... 今天百科达人给各位分享华为下载未安装的文件去哪找的知识,其中也会对华为下载未安装的文件去哪找到进行解...
怎么往应用助手里添加应用(应用... 今天百科达人给各位分享怎么往应用助手里添加应用的知识,其中也会对应用助手怎么添加微信进行解释,如果能...
家里可以做假山养金鱼吗(假山能... 今天百科达人给各位分享家里可以做假山养金鱼吗的知识,其中也会对假山能放鱼缸里吗进行解释,如果能碰巧解...
四分五裂是什么生肖什么动物(四... 本篇文章极速百科小编给大家谈谈四分五裂是什么生肖什么动物,以及四分五裂打一生肖是什么对应的知识点,希...
一帆风顺二龙腾飞三阳开泰祝福语... 本篇文章极速百科给大家谈谈一帆风顺二龙腾飞三阳开泰祝福语,以及一帆风顺二龙腾飞三阳开泰祝福语结婚对应...
美团联名卡审核成功待激活(美团... 今天百科达人给各位分享美团联名卡审核成功待激活的知识,其中也会对美团联名卡审核未通过进行解释,如果能...