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.如果没有为一个类 ...
随机推荐
- js学习:return arguments
return函数 arguments
- 12 IO流
File类:构造方法 * File(String pathname):根据一个路径得到File对象 * File(String parent, String child):根据一个目录和一 ...
- EasyUI datagrid easyui datagrid +dialog 加载 可直接运行 七
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <meta ht ...
- GinKgoCTF-Misc
一:谁动了我的校徽? Jpg改txt——>寻找——>GKCTF{This_is_a_huaji} 二:奇怪的压缩包1 六位数字的密码一点也不安全!!!!!! 下载压缩包——>有密码( ...
- hdu2174 kiki's game 博弈
Recently kiki has nothing to do. While she is bored, an idea appears in his mind, she just playes th ...
- 【mysql】索引原理-MySQL索引原理以及查询优化
转载:https://www.cnblogs.com/bypp/p/7755307.html 一.介绍 1.什么是索引? 一般的应用系统,读写比例在10:1左右,而且插入操作和一般的更新操作很少出现性 ...
- HTTP长连接、短连接究竟
HTTP长连接.短连接究竟是什么? 1. HTTP协议与TCP/IP协议的关系 HTTP的长连接和短连接本质上是TCP长连接和短连接.HTTP属于应用层协议,在传输层使用TCP协议,在网络层使用I ...
- sqler sql 转rest api 数据校验的处理
早期版本(2.0 之前)使用rules 进行数据校验处理,2.0 之后进行了修改使用 validators,这样更加明确 参考格式 addpost { // if any rule retu ...
- IBM MQ相关 ---- 系列文章
原 IBM websphere MQ远程队列的简单配置 转 MQ7.5以后的权限问题解决 原 MQ--API总结 转 连接IBM MQ原因码报2035的错误解决办法 原 Java连接MQ的实例 转 通 ...
- Use swig + lua quick guide
软件swigwin3 用于生成c的lua包装lua5.2源代码 步骤进入目录G:\sw\swigwin-3.0.12\Examples\lua\arrays执行 SWIG -lua ex ...