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++程序员没有犯错,那么这个类本身一定只含有内置类型成员或"自控"的自定义类型成员,没有需要手动释放的资源。

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

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

默认移动赋值完全类似。

相关内容

热门资讯

透视脚本!德普之星怎么作弊,w... 透视脚本!德普之星怎么作弊,wpk辅助购买,教你攻略(有挂揭秘);一、德普之星怎么作弊AI软件牌型概...
透视辅助!禅游游戏辅助脚本(辅... 透视辅助!禅游游戏辅助脚本(辅助挂)竟然真的有挂(详细辅助切实教程);1、在禅游游戏辅助脚本ai机器...
智星菠萝辅助怎么买!hhpok... 智星菠萝辅助怎么买!hhpoker德州机器人(透视)一直是真的有挂(解密教程)1、进入游戏-大厅左侧...
透视规律!wpk脚本辅助器,a... 透视规律!wpk脚本辅助器,aapoker透视脚本,解密教程(有挂黑科技)1、每一步都需要思考,不同...
透视辅助!泸州大二辅助(辅助挂... 透视辅助!泸州大二辅助(辅助挂)真是真的有挂(详细辅助攻略教程)1、在泸州大二辅助ai机器人技巧中,...
wepoker辅助下载!hhp... wepoker辅助下载!hhpoker辅助软件(透视)好像是有挂(新2025版);1、玩家可以在hh...
透视教学!德普之星辅助器,德普... 透视教学!德普之星辅助器,德普之星辅助功能如何打开,我来教教你(有挂辅助)进入游戏-大厅左侧-新手福...
透视辅助!广东雀神麻雀控制器(... 透视辅助!广东雀神麻雀控制器(辅助挂)本来是真的有挂(详细辅助安装教程);1、广东雀神麻雀控制器透视...
wpk透视辅助方法!wepok... 您好,wpk透视辅助方法这款游戏可以开挂的,确实是有挂的,需要了解加去Q群【1067239143】很...
透视ai代打!wpk辅助工具下... 透视ai代打!wpk辅助工具下载,wpk透视脚本下载,wpk教程(有挂攻略)1.wpk透视脚本下载 ...