IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> 《C++ Primer 第5版》-13.1拷贝、赋值与销毁-康奈尔笔记 -> 正文阅读

[C++知识库]《C++ Primer 第5版》-13.1拷贝、赋值与销毁-康奈尔笔记

13.1.1拷贝构造函数

  1. 拷贝、赋值与销毁
  2. 拷贝构造函数
  3. 合成拷贝构造函数
  4. 拷贝初始化
  5. 参数和返回值
  6. 拷贝初始化的限制
  7. 编译器可以绕过拷贝构造函数

拷贝构造函数、拷贝赋值运算符、移动构造函数、移动赋值运算符 析构函数。拷贝控制操作

合成拷贝构造函数

拷贝初始化

Explicit

Foo(const Foo&);

String dot(10,’.’))//直接初始化

String s(dot);//直接初始化

String s3 = s2;//拷贝

String s4 = “999”;//拷贝

String s5 = string(100,’9’);拷贝

F(vector<int>(10));

1. 拷贝、赋值与销毁

1)定义一个类时,显式或隐式地指定在此类型的对象拷贝、移动、赋值和销毁时做什么。通过五种特殊的成? 员函数来控制这些操作

2)一个类没有定义的话,编译器会合成,但是对于一些类来说,使用合成的版本不好,并非我们所需

2. 拷贝构造函数

????当用同类型的另一个对象初始化本对象时做什么,就是在初始化的时候,右侧对象可以先隐式转换对象再通过 = 赋给左侧运算对象

1)拷贝构造函数的第一个参数必须是一个引用类型且任何额外参数都有默认值,并且不应该是explicit的因为? 需要隐式地被使用

3. 合成拷贝构造函数

1)合成的版本是将参数的成员逐个拷贝到正在创建的对象中,非static成员。

2)拷贝方式由每个成员的类型决定:类类型成员,使用拷贝构造函数,内置类型成员,直接拷贝。数组不能? 直接拷贝,合成版本会逐元素地拷贝一个数组类型的成员。如果数组元素是类类型,使用元素的拷贝构造来进行拷贝

4. 拷贝初始化

1)直接初始化:使用普通的函数匹配选择匹配的构造函数

2)拷贝初始化:将右侧运算对象拷贝到正在创建的对象中,如果需要的话要进行类型转换

3)拷贝初始化不仅在 = 定义变量时发生,还有:

? ? ? 一个对象作为实参传给非引用类型的形参

? ? ?从一个返回类型为非引用类型的函数返回一个对象

? ? ?用花括号列表初始化一个数组中的元素或聚合类的成员

4)某些类类型还会对他们所分配的对象使用拷贝初始化。如:容器使用insert或push容器会对其元素进行拷? 贝初始化。相对的,用emplace成员创建的元素都进行直接初始化。

5. 参数和返回值

1)如上,非引用类型的参数要进行拷贝初始化,所以我们的拷贝构造函数的参数要是引用类型,会循环。

6. 拷贝初始化的限制

1)使用了explicit的拷贝构造函数需要显示使用构造函数。

7. 编译器可以绕过拷贝构造函数

1)Test1 t2 = Test1("sdfsd");// 这个直接构造对象,不会发生拷贝构造

2)Test1 t1("sdfsdf");// 也是直接构造对象,应该是直接使用函数,不会发生拷贝构造

3)Test1 t3 = string("sdfsd");//直接构造对象,不会发生拷贝构造

??????以上三个都会使用string的构造函数,不会发生拷贝构造

? ? ? 只有以下两种

1)Test1 t4(t1);// 显示调用拷贝构造函数 接受一个t1对象

2)Test1 t5 = t2;// 隐式调用拷贝构造函数

13.1.2拷贝赋值运算符

  1. 拷贝赋值运算符
  2. 重载赋值运算符
  3. 合成拷贝赋值运算符

Sal trans,accum;

Trans = accum;

Foo& operator=(const Foo&);

合成拷贝赋值运算符

1. 拷贝赋值运算符

1)是用同类型的另一个对象给当前对象赋值时,但是不是初始化,是已经定义过了的后再用同类型的另一个? 对象赋值,也是用=赋值运算符

2. 重载赋值运算符

1)重载=运算符,一个返回类型和一个参数列表

2)返回一个指向其左侧运算对象的引用(*this)

3)参数列表是一个与其所在类相同类型,是引用并且是const,右侧运算对象作为显式参数传递

Note:通常应该返回一个指向其左侧运算对象的引用

3. 合成拷贝赋值运算符

1)合成拷贝赋值运算符用来禁止该类型对象的赋值。若不用用此目的,需将右侧运算对象的每个非static成员赋予左侧运算对象的对应成员

13.1.3析构函数

  1. 析构函数
  2. 析构函数完成什么工作
  3. 什么时候会调用析构函数
  4. 合成析构函数

~Foo();

Int *p = new int(3);

Delete p;

~Sales_data(){}

1. 析构函数

1)析构函数释放对象使用的资源,并且销毁对象的static数据成员

2)是一个成员函数,由波浪号接类名构成,没有返回值,不接受参数

3)析构函数不接受参数,所以不能被重载。一个类只有唯一的析构函数

2. 析构函数完成什么工作

1)首先执行函数体,然后销毁成员,是初始化顺序逆序销毁的

2)析构函数体可以执行类设计者希望执行的任何收尾工作。通常,是释放对象在生存期分配的所有资源

3)不存在初始化列表的东西控制成员如何销毁,析构部分是隐式的

4)完成依赖于成员的类型,类类型的成员需要执行成员自己的析构函数,内置类型没有析构函数,所以说都? 不需做

Note: 所以需要显示销毁一个指针,智能指针是类类型,有析构函数,会自动析构

3. 什么时候会调用析构函数

1)离开作用域

2)对象被销毁,其成员被销毁

3)容器被销毁,其元素被销毁

4)动态分配的对象,delete时

5)临时对象,表达式结束

由于1)所以可以定义普通对象,但是如果是动态分配的对象,需要显示delete,才会执行析构函数

Note:当指向一个对象的引用或指针离开作用域时,不会自动执行析构

4. 合成析构函数

1)析构函数被用来阻止该类型的对象被销毁?不是这种情况,函数体为空

2)空析构函数体执行完成后,成员会被自动销毁。如:执行完析构函数体,执行stirng类型的析构函数销毁? ? bookno

3)析构函数体自身并不直接销毁成员,是在析构函数体之后隐含的析构阶段中被销毁的

13.1.4三五法则

  1. 三/五法则
  2. 需要析构函数的类也需要拷贝和赋值操作
  3. 需要析构函数的类也需要拷贝和赋值操作

1. 三/五法则

1)并不要求定义所有这些操作,可以只定义其中一个两个,而不必定义所有。但是这些操作通常应该被看做一个整体。

2. 需要析构函数的类也需要拷贝和赋值操作

1)是否决定要拷贝控制成员,由是否需要一个析构函数决定,如果需要一个析构,则也明显要拷贝构造和赋值运算符

2)因为若类中有一个动态资源,需要显示delete,但如果默认的控制操作,会将地址传给新的对象,那么执? 行两个对象的析构会删除两次那个地址内存,那么就是不可取的

Note: 如果需要一个析构,则也明显要拷贝构造和赋值运算符

3. 需要析构函数的类也需要拷贝和赋值操作

1)某些类的所要完成的工作,只需要拷贝或赋值操作,不需要析构函数

2)那么拷贝或赋值就绑定在一起,若一个类需要一个拷贝构造函数,那么也要拷贝赋值运算符

3)相反,若要赋值肯定要拷贝,但不一定要析构

Note: 若一个类需要一个拷贝构造函数,那么也要拷贝赋值运算符相反,若要赋值肯定要拷贝,但不一定要析构

13.1.5使用=default

Sales_data()=default;

Sales_data(const Sales_data&)=default;

Sales_data& operator=(const Sales_data&)

~Sales_data()=default;

Sales_data& Sales_data::operator=(const Sales_data&) =default;

1. 使用=default

1)可以通过成员定义为=default来显式要求编译器生成合成的版本

2)声明后为内联了,不想为内联就需要在类外使用=default

Note: 只能对具有合成版本的成员函数使用=default 默认函数或者拷贝控制成员

13.1.6阻止拷贝

  1. 阻止拷贝
  2. 定义删除的函数
  3. 析构函数不能是删除的成员
  4. 合成的拷贝控制成员可能是删除的
  5. private控制拷贝

Nocopy(const Nocopy&)=delete;

Private:

Nocopy(const Nocopy&);

1. 阻止拷贝

1)对某些类来说拷贝赋值和拷贝构造没有合理的意义,必须采用某种机制阻止

2)如:iostream不能拷贝,若采取不定义方式是不可的,因为编译器会合成一个

2. 定义删除的函数

1)删除的函数:虽然声明了他们,但不能以任何方式使用它们

2)在函数参数列表后面加上=delete指明

3)=delete必须出现在第一次声明地方

4)适合所有函数,不同于default只适合拷贝控制

5)当我们希望引导函数匹配过程时,删除函数有时也是很有用的

3. 析构函数不能是删除的成员

1)只是规定,非要定义删除的话,不允许定义该类型的变量或创建该类的临时对象

2)但是可以动态分配,但是delete不掉

4. 合成的拷贝控制成员可能是删除的

? ? 编译器可能会将这些合成的拷贝控制成员定义为删除的

1)若类的某个成员的析构函数是删除的或者不可访问,这个类的析构函数被定义删除

2)若类的某个成员的拷贝构造函数或者析构函数是删除的或者不可访问,这个类的拷贝构造函数被定义删除

3)若类的某个成员的拷贝赋值运算符是删除的或者不可访问,或者有一个const或引用成员,则这个类合成的拷贝赋值运算符被定义删除的

4)若类的某个成员的析构函数是删除的或者不可访问,或类有一个引用成员它没有类内初始化器,或者const成员 它没有类内初始化器(在类内指定默认值)且其类型未显示定义默认构造函数则该类的默认构造函数被定义为删除的

note:如果类的某个成员不能构造、拷贝 复制或销毁,则对应的成员函数被定义为删除

5. private控制拷贝

1)新标准之前,通过将拷贝构造 赋值声明为private来阻止拷贝

2)友元和成员函数仍旧可以拷贝对象,可以通过声明不定义方式,来让链接时错误

3)尽量用delete,而不是private

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-01-01 13:42:06  更:2022-01-01 13:44:33 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 11:06:37-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码