C++右值引用和移动语义
创始人
2025-01-07 18:03:26
0

目录

概念:

左值引用和右值引用

概念:

注意:

左值引用的意义

作函数参数

函数引用返回

右值引用的意义

诞生背景

移动构造

移动赋值

其他应用

万能引用和完美转发

默认的移动构造和移动赋值


概念:

左值:顾名思义,可以在等号左边出现的被叫做左值,左值可以取地址。

右值:只能在等号右边出现的值为右值,且右值不能取地址。

例如

//左值 int a = 2; string s="hello"; const int b=3; int* pa=&a; //右值 3;//字面常量 a + 2;//表达式 add(2, 3);//函数返回值

左值引用和右值引用

概念:

左值引用是用来引用左值的,给左值起别名:

int a = 2;//左值 int& ra = a;//左值引用

右值引用是用来引用右值的,给右值起别名:

int&& rc = 5;//右值引用

注意:

左值引用只能引用左值,因为如果引用右值会导致权限的放大:

int& ra = 2;//权限放大,编译错误

但是左值引用加上const就可以引用右值:

const int& ra = 2;

右值引用只能引用右值,但是可以引用move后的左值

int a = 2;//左值 int&& ra = move(a);

左值引用的意义

作函数参数

C++引用底层是C语言的指针,所以在作为函数参数时可以减少拷贝或者作为输出型参数使用。

void func(const string& s)//输入型参数,const&既可以减少拷贝又可以防止改变引用的实体 { 	cout << s << endl; } void add(int& a)//作为输出型参数 {     a=2; }

函数引用返回

出了函数栈帧,返回变量不会销毁的就可以用引用返回,减少拷贝。否则会导致内存越界。

string ss="hello"; const string& func() { 	return ss;//ss是全局变量,出函数栈帧不会销毁,用引用返回就不会生成临时变量 }

右值引用的意义

诞生背景

普通函数传值返回时,由于函数栈帧出作用域会销毁,其内定义的变量会被释放,所以会返回一个临时对象,这个临时对象是要返回对象的拷贝。

此时,我们会想:既然局部变量s马上就要销毁了,那么我们是否可以将它的资源交换给临时变量呢,这样临时变量的创建就不需要耗费拷贝的代价了

C++把这种即将要销毁的自定义对象称为将亡值,在拷贝将亡值的时,可以利用右值引用在拷贝构造和赋值运算符重载函数中接收将亡值,并实现资源的置换,进而减少无意义的拷贝。

移动构造

在拷贝构造的实现中,实现一份形参使用右值引用接收的拷贝构造(即移动构造),当使用将亡值拷贝构造时,编译器会自动匹配移动构造,在移动构造内实现资源的互换

移动赋值

在赋值运算符重载的实现中,实现一份形参使用右值引用接收的赋值运算符重载(即移动赋值),当使用将亡值赋值时,编译器会自动匹配移动赋值,在移动赋值内实现资源的互换

C++11后,基本所有的STL容器都新增了移动构造和移动赋值,以此来提高需要深拷贝的容器是将亡值时的拷贝效率。

其他应用

除此之外,右值引用在其他接口中也大放异彩:

STL容器插入数据的接口:当插入需要深拷贝对象的右值时,减少拷贝

std::swap交换函数:

万能引用和完美转发

当函数模板和右值引用组合:万能引用既可以引用左值,又可以引用右值

万能引用又叫做引用折叠,即传入右值时&&,传入左值时折叠&。


右值引用的作用就是限制了接收变量只能是右值,但是右值引用本身会退化为左值:

template void func(T&& val)//万能引用 { 	cout << val << endl;//就算原本接收的是右值,右值引用val退化为左值 } int main() { 	func(10); 	return 0; }

完美转发:保留对象原生类型属性,即保持它的左值或者右值的属性

template void func(T&& val)//万能引用 { 	cout << std::forward(val) << endl;//这里使用完美转发保留传入之前的属性 } int main() { 	func(10); 	return 0; }

默认的移动构造和移动赋值

默认移动构造:

如果你没有自己实现移动构造函数,且没有实现析构函数 、拷贝构造、拷贝赋值重载中的任
意一个。那么编译器会自动生成一个默认移动构造。默认生成的移动构造函数,对于内置类
型成员会执行逐成员按字节拷贝,自定义类型成员,则需要看这个成员是否实现移动构造,
如果实现了就调用移动构造,没有实现就调用拷贝构造

解释:

分析上述定义,默认移动构造就是在析构函数 、拷贝构造、赋值重载都没有写,且移动构造也没有显式实现的情况下,编译器会默认生成。

当析构函数,拷贝构造、赋值重载都没有写的时候,且默认C++程序员没有犯错,那么这个类本身一定只含有内置类型成员或"自控"的自定义类型成员,没有需要手动释放的资源。

此时编译器就要做事了,默认生成一份移动构造,当别人调用默认移动构造,来将自定义类型中可以移动构造的对象自动调用移动构造,增加效率,非常合理。

反着思考:如果一个类内有资源需要手动释放,那么析构函数 、拷贝构造、赋值重载一定都要手动写,此时就算我们不手动写移动构造,编译器也不会默认生成,因为编译器不会知道哪些资源需要转移。

默认移动赋值完全类似。

相关内容

热门资讯

两分钟演示!闲来辅助软件靠谱吗... 两分钟演示!闲来辅助软件靠谱吗,新世界辅助器免费下载(辅助)总是真的有下载(哔哩哔哩)两分钟演示!闲...
六分钟阶段!闲来辅助软件怎么样... 六分钟阶段!闲来辅助软件怎么样,新超圣辅助器(辅助)真是真的有工具(哔哩哔哩)闲来辅助软件怎么样辅助...
第十分钟方式!途游辅助软件网站... 第十分钟方式!途游辅助软件网站,随意玩5元流量包(辅助)好像有挂安装(哔哩哔哩)1、下载好途游辅助软...
六分钟总结!蜀渝牌乐汇挂机软件... 六分钟总结!蜀渝牌乐汇挂机软件,海贝之城有辅助吗(辅助)好像是有软件(哔哩哔哩)蜀渝牌乐汇挂机软件能...
第3分钟攻略!崇阳斗棋bug,... 第3分钟攻略!崇阳斗棋bug,天酷游戏交易平台(辅助)一贯有挂辅助(哔哩哔哩)天酷游戏交易平台破解侠...
5分钟举措!海豹大厅超级三加一... 5分钟举措!海豹大厅超级三加一辅助,青龙辅助最新下载(辅助)其实是真的修改器(哔哩哔哩)1、下载好海...
9分钟法子!新悠悠辅助,小程序... 9分钟法子!新悠悠辅助,小程序财神十三水脚本时评(辅助)一直有挂下载(哔哩哔哩)1)小程序财神十三水...
第十分钟指南!新蜜瓜大厅免费控... 第十分钟指南!新蜜瓜大厅免费控制器,三加一辅助(辅助)都是存在有脚本(哔哩哔哩)该软件可以轻松地帮助...
第五分钟学习!创思维激k软件助... 第五分钟学习!创思维激k软件助手,西兵互娱辅助插件app(辅助)切实存在有安装(哔哩哔哩)1、玩家可...
第1分钟总结!海盗来了大白辅助... 第1分钟总结!海盗来了大白辅助,海贝之城辅助器(辅助)原来是有平台(哔哩哔哩)一、海盗来了大白辅助可...