C++新特性探究(十六):move constructor移动构造
相关博文:
C++新特性探究(十三):右值引用(r-value ref)&&探究
C++新特性探究(十六):move constructor移动构造
C++新特性探究(13.5):右值引用
C++新特性探究(13.6):右值引用再探究
附加语:栈对象可以返回,栈对象的引用不可以返回
移动构造本质特定意义(使用场景下的浅拷贝),取名为移动构造,解决的还是效率问题。
一. 拷贝语义
对于类中,含有指针的情况,即含有堆内存资源的情况,要自实现其拷贝构造和拷贝赋值。也就是所谓的深拷贝和深赋值。已经是一种共识:
例.深拷贝——以前的固定式思维:对象中含有堆上的资源–>深拷贝
例.浅拷贝
例.右值引用
上面的过程,我们已经知晓,ret作为右值引用,引用了临时对象,由于临时对象是待返回对象的复本,所以表面上看起来是,待返回对象的作用域扩展了,生命周期也延长了。
附上例代码:
//小问学编程——浅拷贝
#include <iostream>
using namespace std;
class HasPtrMem
{public:HasPtrMem():_d(new int(100)){cout<<"HasPtrMem()"<<this<<endl;}
// HasPtrMem(const HasPtrMem& another)
// :_d(new int(*another._d))
// {// cout<<"HasPtrMem(const HasPtrMem& another)"<<
// this<<"->"<<&another<<endl;
// }~HasPtrMem(){delete _d;cout<<"~HasPtrMem()"<<this<<endl;}int * _d;
};
HasPtrMem getTemp()
{return HasPtrMem();
}int main(int argc, char *argv[])
{HasPtrMem a;HasPtrMem b(a);cout<<a._d<<endl;cout<<b._d<<endl;cout<<*a._d<<endl;cout<<*b._d<<endl;//HasPtrMem&& ret = getTemp();return 0;
}
二. 移动构造
栈对象,返回,拷贝不可避免,能不能减少拷贝的代价?
如不是,移动构造函数。我们借用临时变量,将待返回对象的内容“偷”了过来。移动构造的本质,也是一种浅拷贝,但此时的浅拷贝已经限定了其使用的场景,故而是安全的。
例:
附上例代码:
//小问学编程
#include <iostream>
using namespace std;
class HasPtrMem
{public:HasPtrMem():_d(new int(0)){cout<<"HasPtrMem()"<<this<<endl;}HasPtrMem(const HasPtrMem& another):_d(new int(*another._d)){cout<<"HasPtrMem(const HasPtrMem& another)"<<this<<"->"<<&another<<endl;}HasPtrMem(HasPtrMem &&another){cout<<this<<" Move resourse from "<<&another<<"->"<<another._d<<endl;_d = another._d;another._d = nullptr;}~HasPtrMem(){if(_d != nullptr)delete _d;cout<<"~HasPtrMem()"<<this<<endl;}int * _d;
};
HasPtrMem getTemp()
{return HasPtrMem();
}
int main(int argc, char *argv[])
{HasPtrMem&& a = getTemp();return 0;
}
三. 关于默认
对于不含有资源的对象来说,自实现拷贝与移动语义并没有意义,对于这样的类型而言移动就是拷贝,拷贝就是移动。
拷贝构造/赋值 和 移动构造/赋值,必须同时提供或是同时不提供。才能保证同时俱有拷贝和移动语义。只声明一种的话,类只能实现一种语义。
只有拷贝语义的类,也就是 C++98 中的类。而只有移动语义的类,表明该类的变量所拥有的资源只能被移动,而不能被拷贝。那么这样的资源必须是唯一的。只有移动语义构造的类型往往时"资源型"的类型。
比如智能指针,文件流等。
例:
//小问学编程
#include <iostream>
#include <memory>
using namespace std;
class Copy
{public:Copy(int i=0):_i(new int(i)){cout<<"Copy(int i)"<<endl;}Copy(const Copy & another):_i(new int(*another._i)){cout<<" Copy(const Copy & another)"<<endl;}Copy & operator=(const Copy & another){cout<<" Copy & operator=(Copy & another)"<<endl;if(this == &another) return *this;delete _i;_i = new int(*another._i);return *this;}~Copy(){delete _i;cout<<"~Copy()"<<endl;}int *_i;
};
class Move
{public:Move(int i=0):_i(new int(i)){cout<<"Move(int i)"<<endl;}Move( Move && another){cout<<" Move( Move && another)"<<endl;_i = another._i;another._i = nullptr;}Move & operator=(Move && another){cout<<" Move & operator=(Move && another)"<<endl;if(this != &another){delete _i;_i = another._i;another._i = nullptr;}return *this;}~Move(){if(_i != nullptr)delete _i;cout<<"~Move()"<<endl;}int *_i;
};
Copy getCopy()
{return Copy(1);
}
Move getMove()
{return Move(1);
}
int main(int argc, char *argv[])
{Move m;Move n(m);Copy m;Copy n(m);
// Move m(100);
// Move n(m); //编译不过,没有拷贝构造器,两者的互斥性
// Copy rc = getCopy();
// Move rm = getMove();Copy &&rrc = getCopy();Move &&rrm = getMove();return 0;
}
四. 慎用移动
拷贝,无疑是安全的,而移动,无疑是高效的。但是这种高效前提你对资源的深刻a的理解,否则可能带来极大的安全隐患的,所以要慎用。
移动解决了,如下第一个拷贝的效率问题,引用,解决了,如下第二个拷贝的效率问题。
C++11 注定是高效的。
C++新特性探究(十六):move constructor移动构造相关推荐
- C++新特性探究(十五):bind
相关博文:C++新特性探究(十四):function 相关博文:C++头文件<functional>和bind.placeholders占位符使用简单例子 相关博文:<Essenti ...
- C++新特性探究(十四):function
相关博文:C++头文件<functional>和bind.placeholders占位符使用简单例子 相关博文:<Essential C++>笔记之设计一个泛型算法(二) 相关 ...
- C++新特性探究(十):Lambda
一. 匿名函数 简短函数,就地书写,调用.即Lambda存在的意义,常用于取代作回调用的简短函数指针与仿函数. 就地书写,因只有函数体,即无函数名,也称匿名函数. 格式 最小的 Lambda: ...
- C++新特性探究(十八):智能指针
一.智能指针及RAII 问题: C++中最令人头疼的问题是强迫程序员对申请的资源(文件,内存等)进行管理,一不小心就会出现泄露(忘记对申请的资源进行释放)的问题. C++的解决办法:RAII ...
- C++新特性探究(十二):static_assert(提前判误)
相关博文:C++之异常处理探究 相关博文:assert.if else.try catch三者的区别 相关博文:C++之assert.NDEBUG探究 相关博文:static_assert和asser ...
- C++新特性探究(13.6):右值引用再探究
相关博文: C++新特性探究(十三):右值引用(r-value ref)&&探究 C++新特性探究(十六):move constructor移动构造 C++新特性探究(13.5):右值 ...
- C++新特性探究(13.5):右值引用
相关博文: C++新特性探究(十三):右值引用(r-value ref)&&探究 C++新特性探究(十六):move constructor移动构造 C++新特性探究(13.5):右值 ...
- C++新特性探究(十三):右值引用(r-value ref)探究
相关博文: C++新特性探究(十三):右值引用(r-value ref)&&探究 C++新特性探究(十六):move constructor移动构造 C++新特性探究(13.5):右值 ...
- Java 8新特性探究(二)深入解析默认方法
转载自 Java 8新特性探究(二)深入解析默认方法 什么是默认方法,为什么要有默认方法 简单说,就是接口可以有实现方法,而且不需要实现类去实现其方法.只需在方法名前面加个default关键字即可. ...
最新文章
- 野火开发版屏幕_盘一盘那些年我们常用的物联网开发板!
- ML之LoRDTRF:基于LoRDT(CART)RF算法对mushrooms蘑菇数据集(22+1,6513+1611)训练来预测蘑菇是否毒性(二分类预测)
- hosts和resolv.conf区别
- mysql+主从复制重做_XtraBackup实现MySQL不停机重做主从复制
- 使用DIV之后 table何去何从
- Python除了不会生孩子,什么都会
- win下svn常用操作笔记
- linux 一句话备忘
- Vue 报错Error: No PostCSS Config found解决办法
- Django模型(model)系统
- 树莓派摄像头,协议相关,人脸、车牌识别
- Unity 基础资源知识汇总学习
- 金刚石切割丝的全球与中国市场2022-2028年:技术、参与者、趋势、市场规模及占有率研究报告
- Ubuntu安装后初次配置
- java半角英数check_java - 关于全角半角介绍以及处理方式
- GitHub上传教程,图文并茂
- 做大数据论文时的分析思路
- 高级计划和排程(APS)软件的功能与用途
- 【swagger2】Spring Boot 配置swagger2
- Blinker控制esp8266 01s实现远程控制继电器开关代码
热门文章
- thymeleaf的属性优先级
- 基于JAVA+SpringMVC+Mybatis+MYSQL的房屋租赁系统
- ASP.NET Core学习——7
- C#使用CurrentUICulture切换语言
- 我的MySQL数据库学习笔记
- IO流-LineNumberReader
- java字符类型的返回值,Java字符类isWhitespace()方法及示例
- 解决编写C#在vscode上面不能输入问题
- centOS 8+VMwware配置(2)
- 外观模式和代理模式的联系和区别_设计模式之代理模式