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.如果没有为一个类 ...
随机推荐
- jQ常用选择器
#id: $('#div'); //查找id='div'; .class: $('.myclass'); //查找class='myclass'; element:用于搜索的元素,指向DOM节 ...
- pat--7-11 出栈序列的合法性(25 分)
7-11 出栈序列的合法性(25 分) 给定一个最大容量为 M 的堆栈,将 N 个数字按 1, 2, 3, ..., N 的顺序入栈,允许按任何顺序出栈,则哪些数字序列是不可能得到的?例如给定 M=5 ...
- 1001.A+B Format (20)题目解答
前言 最开始看到这个题目,我的第一个想法是有没有那种输出格式可以直接拿来用的,然后我百度了一下,想偷懒,然而并没有这种东西.只好动动自己的脑子了. 关于GitHub 这个问题,当初我弄了五天才建立好联 ...
- C++学习(十)(C语言部分)之 分支语句
#include<stdio.h> // std 标准 io ----> input output 输入 输出 printf scanf getchar ...... #i ...
- hdu2609 How many 字典树+最小表示法
Give you n ( n < 10000) necklaces ,the length of necklace will not large than 100,tell meHow many ...
- String的intern()方法详解
https://blog.csdn.net/soonfly/article/details/70147205 :图解 https://blog.csdn.net/wjzhang5514/articl ...
- linux(Centos7)服务器硬件改动,进入Emergency模式
例如移走了某块硬盘后,直接开机就会进入该模式 这是因为/etc/fstab没有正确执行的原因 解决方法: 1)在该模式下输入root密码进入单用户模式(我没试过,不知道行不行,如果不行的话就用忘记ro ...
- .NET本质论 实例
对象和值的比较 CLR的类型系统(其实就是通用类型系统(CTS),它定义了如何在运行库中声明,使用和管理类型,同时也是运行库支持跨语言集成的一个重要组成部分)将对应简单值的类型同对应传统"对 ...
- C# 自动升级
自动更新的软件的目的在于让客户不在为了寻找最新软件花费时间.也不用去到开发商的网站上查找.客户端的软件自动会在程序启动前查找服务器上最新的版本.和自己当前软件的版本比较,如果服务器的是最新版本.客户端 ...
- 求Sn=a+aa+aaa+aaaa+aaaaa的前5项之和,其中a是一个数字
思路:所求和为一个数字的前n项和,例如前4项和就是从4+44+444+4444,一直加到第4位,为4个4.所以可以用一个循环来表示每一项的数字,加到前几项就循环几次.然后将每项进行相加就可以求出总和. ...