C/C++基础----拷贝控制
拷贝控制操作,有5个特殊成员函数copy ctor,copy =opt,move ctor,move =opt,dtor
有哪些地方会用到
拷贝初始化
除了=定义变量时
参数传递和函数返回时
花括号列表初始化一个数组中元素或一个聚合类中成员
某些类对所分配的对象使用拷贝初始化,如insert和push;相对地,emplace直接初始化
成员是在析构函数体之后隐含的析构阶段中被销毁的
1一个类需要自定义析构函数,几乎可以肯定它也需要自定义拷贝构造和拷贝赋值。
2拷贝构造和拷贝赋值有一个,几乎可以肯定另一个也需要,但是不一定需要析构函数。
- 某些类需要阻止拷贝
如iostream类,避免多个对象写入或读取相同的IO缓冲。
定义为删除的函数来阻止拷贝。
struct NoCopy{
NoCopy() = default; //合成的默认构造函数
NoCopy(const NoCopy&) = delete; //阻止拷贝
NoCopy &operator=(const NoCopy&) = delete; //阻止赋值
~NoCopy() = default; //合成版本
//其他
}
=delete必须出现在第一次声明的时候
=delete可以对任意函数指定,但不能删除析构函数
如果一个类有数据成员不能默认构造、拷贝、赋值或销毁,则对应的成员函数将被定义为删除的。
希望阻止拷贝应该用=delete定义,而不应该声明为private,成员函数和友元函数仍然可以进行拷贝。
管理类外资源的类,通常必须定义拷贝控制成员。首先需要确定此类型对象的拷贝语义,一般有两种选择,使类看起来像一个值或者一个指针。
两种类
- 像值的类:需要深拷贝,定义copy ctor、copy =opt(自赋值)和析构
- 像指针类:使用shared_ptr来管理资源,使用引用计数,拷贝时修改计数,析构时判断
定义类自己的swap
定义类自己的swap是一种优化手段,应该调用swap而不是std::swap。如果存在类型特定的swap版本,匹配程度会优于std版本。
定义了swap的类通常用swap来定义赋值运算符
HasPtr& HasPtr::operator=(HasPtr ths)
{
swap(*this, ths);//ths现在指向本对象曾经使用的内存,不能交换指针局部变量会被销毁
return *this;//rhs被销毁
}
该方法还自动处理了自赋值情况且是天然异常安全的。
在改变左侧运算对象之前拷贝右侧运算对象
唯一可能抛出异常的是拷贝构造函数中new表达式,真出现也会在改变左侧之前就发生。
- 引用与move
左值引用,不能绑定到要求转换的表达式、字面值常量、返回右值的表达式。
const左值引用或者右值引用可以绑定到右值上。
区别:左值有持久的状态,右值要么是字面常量,要么是在表达式求值过程中创建的临时对象。
所以右值引用的对象,将要被销毁,且没有其他用户。这就意味着右值引用的代码可以自由地接管所引用对象的资源,“窃取”其状态。
我们可以显式地将一个左值转换为对应的右值引用类型。还可以通过move来获得绑定到左值的右值引用。<utility>
int &&rr3=std::move(rr1);
move告诉编译器,我们有一个左值,但希望像一个右值一样处理它。调用move意味着除了对rr1赋值和销毁外,不能使用它的值。
移动一个对象数据并不会销毁此对象,但有时移动完成后源对象会销毁。所以编写移动操作时,必须确保源对象进入可析构的安全状态,还必须保证对象仍然是有效的(可以安全地赋予新值或者可以安全地使用而不依赖其当前值)。我们的程序不应该依赖于移后源对象的数据。
当编写一个不抛出异常的移动操作的时候,必须在声明和定义中都指定noexcept。
1虽然移动操作通常不抛出异常,但抛出异常是允许的
2标准库容器能对异常发生时自身的行为提供保证。
除非知道移动不会抛出异常,否则必须用拷贝。同样需要检测自赋值,不能再使用右侧资源前就释放左侧资源。
参数是左值,移动版本赋值不可行,不能隐式地将一个右值引用绑定到一个左值。
参数是右值,两个版本都可以,拷贝=需要一次const转换,移动=则是精确匹配。
所有5个拷贝控制成员应该看做一个整体。
- 移动迭代器
make_move_iterator,解引用后生成一个右值引用。
标准库不保证哪些算法适用于移动迭代器。只有在确信算法在为一个元素赋值或者将其传递给一个用户定义的函数后不再访问它时,才能将移动迭代器传递给算法。
引用限定符& &&,类似const限定符只能用于非static成员函数,且必须同时出现在声明和定义中。const在前,&在后。
对象是一个右值,意味着没有其他用户,因此可以改变对象。
C/C++基础----拷贝控制的更多相关文章
- C++ 拷贝控制和资源管理,智能指针的简单实现
C++ 关于拷贝控制和资源管理部分的笔记,并且介绍了部分C++ 智能指针的概念,然后实现了一个基于引用计数的智能指针.关于C++智能指针部分,后面会有专门的研究. 通常,管理类外资源的类必须定义拷贝控 ...
- C++ Primer : 第十三章 : 拷贝控制之对象移动
右值引用 所谓的右值引用就是必须将引用绑定到右值的引用,我们通过&&来绑定到右值而不是&, 右值引用只能绑定到即将销毁的对象.右值引用也是引用,因此右值引用也只不过是对象的别名 ...
- C++ Primer : 第十三章 : 拷贝控制之拷贝控制和资源管理
定义行为像值的类 行为像值的类,例如标准库容器和std::string这样的类一样,类似这样的类我们可以简单的实现一个这样的类HasPtr. 在实现之前,我们需要: 定义一个拷贝构造函数,完成stri ...
- C++的那些事:类的拷贝控制
1,什么是类的拷贝控制 当我们定义一个类的时候,为了让我们定义的类类型像内置类型(char,int,double等)一样好用,我们通常需要考下面几件事: Q1:用这个类的对象去初始化另一个同类型的对象 ...
- C++ Primer : 第十三章 : 拷贝控制之拷贝、赋值与销毁
拷贝构造函数 一个构造函数的第一个参数是自身类类型的引用,额外的参数(如果有)都有默认值,那么这个构造函数是拷贝构造函数.拷贝构造函数的第一个参数必须是一个引用类型. 合成的拷贝构造函数 在我们没 ...
- Chapter13:拷贝控制
拷贝控制操作:拷贝构造函数.拷贝赋值运算符.移动构造函数.移动赋值运算符.析构函数. 实现拷贝控制操作的最困难的地方是首先认识到什么时候需要定义这些操作. 拷贝构造函数: 如果一个构造函数的第一个参数 ...
- c/c++ 拷贝控制 构造函数的问题
拷贝控制 构造函数的问题 问题1:下面①处的代码注释掉后,就编译不过,为什么??? 问题2:但是把②处的也注释掉后,编译就过了,为什么??? 编译错误: 001.cpp: In copy constr ...
- c/c++ 拷贝控制 右值与const引用
拷贝控制 右值与const引用 背景:当一个函数的返回值是自定义类型时,调用侧用什么类型接收?? 1,如果自定义类型的拷贝构造函数的参数用const修饰了:可以用下面的方式接收. Test t2 = ...
- C++ Primer 笔记——拷贝控制
1.如果构造函数的第一个参数是自身类类型的引用,且任何额外参数都有默认值,则此构造函数是拷贝构造函数.拷贝构造函数的第一个参数必须是引用类型(否则会无限循环的调用拷贝构造函数). 2.如果没有为一个类 ...
随机推荐
- 百练8216-分段函数-2016正式A题
百练 / 2016计算机学科夏令营上机考试 已经结束 题目 排名 状态 统计 提问 A:分段函数 查看 提交 统计 提问 总时间限制: 1000ms 内存限制: 65536kB 描述 编写程序 ...
- Angular 插值字符串
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...
- HDU 1907:John(尼姆博弈变形)
John Time Limit: 5000/1000 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others) Total Submi ...
- FZU软工第四次作业-团队介绍
目录 团队展示----旅法师 团队成员 队名----旅法师 拟作的团队项目描述 队员风采 团队首次合照 团队的特色描述 团队展示----旅法师 本次作业链接 团队成员 031602305 陈玮 031 ...
- 启动tomcat报错:Failed to start component [StandardEngine[Catalina].StandardHost[localhost]
1.右键点击需要启动的tomcat,选择Clean和Clean Tomcat Work Directory,清除即可!
- HDU 1000
A + B Problem Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total ...
- cenos7.0 安装docker
使用yum命令在线安装 yum install docker 安装后查看Docker版本 docker -v启动docker:systemctl start docker停止docker:syste ...
- doubleclick video notes
1,vast duration it must math this format ,if use “00:00:7 ” it will tip “ ” <Duration>00:00:0 ...
- 使用 --image-repository 解决kubeadm 安装k8s 集群 谷歌镜像墙的问题
从网上我们看到的好多kubeadm 安装k8s 的时候都说需要下拉取镜像,然后修改,实际上 我们可以使用配置参数,快速的跳过墙的问题 说明: 基础镜像,我们仍然存在,拉取的问题,但是dockerhub ...
- 曾经很强大的免费 ERP 2BizBox
曾经很强大的免费 ERP 2BizBox 整个功能很强大,特别是生产,工单也很完善,有损耗,有反冲等功能. 流程比较规矩,需要先采购后才能使用,只有生产后才能销售,工单有组装和拆装,工程有工程更改,也 ...