[笔记]C++拷贝构造和移动构造
一、拷贝构造
如果一个构造函数的第一个参数是自身类类型的引用,且任何额外参数都没有默认值,则此构造函数是拷贝构造函数。(《C++Primer,第五版》)
class Foo
{
public :
Foo();
Foo(const Foo&); //拷贝构造函数
Foo& operator=(const Foo&); //拷贝赋值运算符
};
类的成员中有指针时,使用深拷贝。
#include <iostream>
using namespace std; class Foo
{
public:
Foo()
{
pInt = new int;
*pInt = ;
}
Foo(const Foo&)= default; //拷贝构造函数
Foo& operator=(const Foo&) = default; //拷贝赋值运算符 int* pInt;
}; //浅拷贝,foo1和foo2中的pInt指向同一块内存地址
Foo foo1;
Foo foo2(foo1); //深拷贝
class Cop
{
public:
Cop()
{
pInt = new int;
*pInt = ;
}
Cop(const Cop& cop)
{
pInt = new int;
*pInt = *(cop.pInt);
}
int* pInt;
};
//深拷贝,cop1和cop2中pInt指向不同内存
Cop cop1;
Cop cop2(cop1);
二、移动构造
在某些情况下(函数返回对象引用),对象拷贝后立即就被消耗了。拷贝构造就回造成性能上的浪费,而且深拷贝也会造成浪费。移动构造可以避免这种情况的发生。
为了支持移动构造,C++11引入了右值引用。
右值引用:必须绑定到右值的引用,通过&&来获得右值引用,类似左值引用(常规引用),右值应用也是一块内存的别名。
右值:字面常量、在表达式求值过程中临时创建的对象,这些使用过后就被销毁的资源。不同于左值的持久状态。
因此,右值引用只能绑定到将要被销毁的对象上,左值引用只能绑定到持久的对象上。
//例子来源于 《C++primer 第五版》 int i = ;
int& r = i; //正确,i是左值
int&& rr = i; //错误
int& r2 = i * ; //错误,i*42是右值,用完即销毁
const int& r3 = i * ; //正确,隐式转换为左值后,r3引用
int&& rr2 = i * ; //正确,绑定右值
int&& rr1 = 42; //正确,字面常量是右值
int&& rr2 = rr1; //错误,rr1左值
变量都是左值,因此无法将右值引用绑定到一个右值引用类型的变量上。
如果要将右值引用绑定到左值上,可以通过move函数来获得左值的右值引用类型。对一个左值调用move函数后,除了对该左值赋值和销毁外,不再使用它。
int i = ;
int&& rr = move(i); //i和rr引用同一块内存 i = ; cout << i << endl;
cout << rr << endl;
移动构造函数依靠右值引用特性来将来改变内存的管理者,而不同于拷贝构造对内存进行拷贝。
移动构造:第一个参数是该类类型的一个右值引用,且任何额外的参数都必须有默认实参。使用移动构造函数必须确保销毁移后源对象是无害的(不会重复释放同一块内存)。
Cop(Cop&& cop) noexcept : pInt(cop.pInt)
{
cout << "this is &&" << endl;
cop.pInt = NULL;
}
Cop& operator=(Cop&& cop) noexcept
{
if ( this == &cop ) return *this;
cout << "this is && =" << endl;
delete pInt;
pInt = cop.pInt;
cop.pInt = NULL; } Cop retCop()
{
Cop cop3;
*cop3.pInt = ;
return cop3;
} //调用移动赋值运算符,cop3中pInt接管retCop返回对象中的pInt指向内存
Cop cop3 = retCop();
noexcept承诺函数不抛出异常,标准库对这个函数不做额外处理。
[笔记]C++拷贝构造和移动构造的更多相关文章
- Effective C++_笔记_条款09_绝不在构造和析构过程中调用virtual函数
(整理自Effctive C++,转载请注明.整理者:华科小涛@http://www.cnblogs.com/hust-ghtao/) 为方便采用书上的例子,先提出问题,在说解决方案. 1 问题 1: ...
- C++ 构造中调用构造
//构造中调用构造 #define _CRT_SECURE_NO_WARNINGS #include<iostream> using namespace std; class Point{ ...
- 《Effective C++》读书笔记 被你忽略的关于构造析构赋值
如果程序员没有定义,那么编译器会默认隐式为你创建一个copy构造函数,一个copy赋值操作符,一个析构函数.另外如果你没有声明任何构造函数,编译器会为你声明一个default构造函数. 但是只有当这些 ...
- C++深度解析教程学习笔记(6)对象的构造和销毁
1. 对象的初始化 (1)从程序设计的角度看,对象只是变量,因此: ①在栈上创建对象时,成员变量初始化为随机值 ②在堆上创建对象时,成员变量初始化为随机值 ③在静态存储区创建对象时,成员变量初始化为 ...
- C#线程学习笔记五:线程同步--事件构造
本笔记摘抄自:https://www.cnblogs.com/zhili/archive/2012/07/23/Event_Constructor.html,记录一下学习过程以备后续查用. 前面讲的线 ...
- STL——容器(Set & multiset)的默认构造 & 带参构造 & 对象的拷贝构造与赋值
1. 默认构造 set<int> setInt; //一个存放int的set容器. set<float> setFloat; //一 ...
- C++ 笔记(二) —— 不要在构造和析构函数中调用虚函数
ilocker:关注 Android 安全(新手) QQ: 2597294287 class Transaction { //所有交易的 base class public: Transaction( ...
- [DeeplearningAI笔记]卷积神经网络1.6-1.7构造多通道卷积神经网络
4.1卷积神经网络 觉得有用的话,欢迎一起讨论相互学习~Follow Me 1.6多通道卷积 原理 对于一个多通道的卷积操作,可以将卷积核设置为一个立方体,则其从左上角开始向右移动然后向下移动,这里设 ...
- JavaScript模式读书笔记 文章3章 文字和构造
1.对象字面量 -1.Javascript中所创建的自己定义对象在任务时候都是可变的.能够从一个空对象開始,依据须要添加函数.对象字面量模式能够使我们在创建对象的时候向其加入函数. ...
随机推荐
- 数值分析-Legendre正交多项式 实现函数逼近
数值分析-Legendre正交多项式 实现函数逼近 2016年12月18日 21:27:54 冰三点水 阅读数 4057 版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请 ...
- 批量Insert
oracle INSERT ALL ,) ,) ,) FROM DUAL
- luogu P3773 [CTSC2017]吉夫特
luogu 这里的组合数显然要用\(\text{lucas}\)定理来求,所以考虑\(\text{lucas}\)定理的本质,即把\(n,m\)分别拆分成\(p\)进制串\(\{a\}\{b\}\), ...
- weblogic 反序列化漏洞 getshell
上传cmd.jsp,效果: 上传马:
- Linux下mysql不区分大小写设置
Linux环境下的MySQL数据库的表名默认是区分大小写的 Windows环境下的MySQL数据库的表名默认是不区分大小写的 所以Linux下想mysql不区分下大写可以查看/etc/my.cnf文件 ...
- 使用ABAP批量下载Markdown源文件里的图片到本地
执行我github里的这个report: 选中一段markdown文档,ctrl C: 然后直接执行report: 执行完毕: 所有文件都下载到本地文件夹: 这个report使用到的工具类:zcl_c ...
- 第三章 Lambda表达式
第三章 Lambda表达式 3.1 函数式编程思想概述 在数学中,函数就是有输入量.输出量的一套计算方案,也就是“拿什么东西做什么事情”.相对而言,面向对象过分强调“必须通过对象的形式来做事情”,而函 ...
- 10_Redis_多数据库
一:概念: 一个Redis实例可以包括多个数据库,客户端可以指定连接某个redis实例的哪个数据库,就好比一个mysql中创建多个数据库,客户端连接时指定连接哪个数据库. 一个Redis实例最多可提供 ...
- STM32F407 CAN发送注意事项
STM32使用的baseCAN,使用过程中发现一些注意的事项,特此记录. 现象: CAN发送程序,在1ms以上间隔调用时,一切正常. 当连续调用CAN发送程序4次或更多时,表现为丢数据,仅能发送一条或 ...
- 在springmvc框架中,通过ajax请求,响应至前端的中文显示是?
今天遇到的一个问题,我通过ajax请求去访问控制器,然后通过控制器给我响应了一段json数据,但是里面的中文 在浏览上显示是??,我在web.xml 文件中是设置了编码过滤器的,但是估计这个编码过滤器 ...