相关博文:
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移动构造相关推荐

  1. C++新特性探究(十五):bind

    相关博文:C++新特性探究(十四):function 相关博文:C++头文件<functional>和bind.placeholders占位符使用简单例子 相关博文:<Essenti ...

  2. C++新特性探究(十四):function

    相关博文:C++头文件<functional>和bind.placeholders占位符使用简单例子 相关博文:<Essential C++>笔记之设计一个泛型算法(二) 相关 ...

  3. C++新特性探究(十):Lambda

    一. 匿名函数   简短函数,就地书写,调用.即Lambda存在的意义,常用于取代作回调用的简短函数指针与仿函数.   就地书写,因只有函数体,即无函数名,也称匿名函数. 格式 最小的 Lambda: ...

  4. C++新特性探究(十八):智能指针

    一.智能指针及RAII 问题:   C++中最令人头疼的问题是强迫程序员对申请的资源(文件,内存等)进行管理,一不小心就会出现泄露(忘记对申请的资源进行释放)的问题. C++的解决办法:RAII    ...

  5. C++新特性探究(十二):static_assert(提前判误)

    相关博文:C++之异常处理探究 相关博文:assert.if else.try catch三者的区别 相关博文:C++之assert.NDEBUG探究 相关博文:static_assert和asser ...

  6. C++新特性探究(13.6):右值引用再探究

    相关博文: C++新特性探究(十三):右值引用(r-value ref)&&探究 C++新特性探究(十六):move constructor移动构造 C++新特性探究(13.5):右值 ...

  7. C++新特性探究(13.5):右值引用

    相关博文: C++新特性探究(十三):右值引用(r-value ref)&&探究 C++新特性探究(十六):move constructor移动构造 C++新特性探究(13.5):右值 ...

  8. C++新特性探究(十三):右值引用(r-value ref)探究

    相关博文: C++新特性探究(十三):右值引用(r-value ref)&&探究 C++新特性探究(十六):move constructor移动构造 C++新特性探究(13.5):右值 ...

  9. Java 8新特性探究(二)深入解析默认方法

    转载自 Java 8新特性探究(二)深入解析默认方法 什么是默认方法,为什么要有默认方法 简单说,就是接口可以有实现方法,而且不需要实现类去实现其方法.只需在方法名前面加个default关键字即可. ...

最新文章

  1. 野火开发版屏幕_盘一盘那些年我们常用的物联网开发板!
  2. ML之LoRDTRF:基于LoRDT(CART)RF算法对mushrooms蘑菇数据集(22+1,6513+1611)训练来预测蘑菇是否毒性(二分类预测)
  3. hosts和resolv.conf区别
  4. mysql+主从复制重做_XtraBackup实现MySQL不停机重做主从复制
  5. 使用DIV之后 table何去何从
  6. Python除了不会生孩子,什么都会
  7. win下svn常用操作笔记
  8. linux 一句话备忘
  9. Vue 报错Error: No PostCSS Config found解决办法
  10. Django模型(model)系统
  11. 树莓派摄像头,协议相关,人脸、车牌识别
  12. Unity 基础资源知识汇总学习
  13. 金刚石切割丝的全球与中国市场2022-2028年:技术、参与者、趋势、市场规模及占有率研究报告
  14. Ubuntu安装后初次配置
  15. java半角英数check_java - 关于全角半角介绍以及处理方式
  16. GitHub上传教程,图文并茂
  17. 做大数据论文时的分析思路
  18. 高级计划和排程(APS)软件的功能与用途
  19. 【swagger2】Spring Boot 配置swagger2
  20. Blinker控制esp8266 01s实现远程控制继电器开关代码

热门文章

  1. thymeleaf的属性优先级
  2. 基于JAVA+SpringMVC+Mybatis+MYSQL的房屋租赁系统
  3. ASP.NET Core学习——7
  4. C#使用CurrentUICulture切换语言
  5. 我的MySQL数据库学习笔记
  6. IO流-LineNumberReader
  7. java字符类型的返回值,Java字符类isWhitespace()方法及示例
  8. 解决编写C#在vscode上面不能输入问题
  9. centOS 8+VMwware配置(2)
  10. 外观模式和代理模式的联系和区别_设计模式之代理模式