今天是周六早上,但很不幸待会儿还是要去公司,本月kpi还剩一些工作要做,这个月计划的Effective C++学习,也基本完成了,最后一章节模板相关那部分还看不太懂,就大概过了一遍。现在是收尾总结阶段了。这本书的准则在这里我想尽量精简化,本篇主要是第二章节的内容:构造、析构和赋值。

5. 了解C++默默编写和调用了哪些函数

创建class时,构造函数和析构函数是非常重要的。构造函数是在创建对象时调用的,涉及到相关成员变量的初始化工作。析构函数则是在销毁对象是调用的,不完备的析构函数很容易造成堆内存泄漏。我们先看构造函数,如果不显式定义构造函数,编译器会默认自动创建构造函数,但一旦我们定义了某个构造函数,编译器将不会为你生成其他构造函数(编译器这里认为你只需要你声明的构造函数),若有需要,使用=default可以告诉编译器生成对应的默认函数。

同样,拷贝构造函数和拷贝赋值运算符如果没有声明,编译器也会自动创建一个默认版本。且这些函数都是public和inline的。注意,默认生成的拷贝构造和拷贝赋值往往会执行浅拷贝,这在有些场景下是危险的。

此外,如若没有声明析构函数,编译器也会生成析构函数,这个析构函数中会依次调用每个成员变量的析构函数。PS:一个对象析构两次会导致行为未定义的错误。

6. 若不想使用编译器生成的函数,就要明确拒绝

上一条准则说明了编译器会自动生成一些成员函数,但当我们需要禁用一些自动生成的函数接口时,我们可以将其声明为private的,例如私有的operator=可以禁止拷贝赋值。在C++11以上版本,我们还可以使用=delete来直接禁止对应方法的调用。

7. 为多态基类声明virtual析构函数

这个准则是和多态调用一致的,当我们将一个子类对象的指针赋给一个父类指针对象时,我们可以通过虚函数表调用到真正的子类方法,而在析构的时候也是一样,只有当基类的析构函数时虚函数的时候,才能先正确调用到子类的析构函数,然后子类的析构函数会自动调用基类的析构函数,从而完成对象资源的完全释放,不会导致内存泄漏。PS:如果一个class带有任何virtual函数,那么就是希望该class在未来会被继承,就有可能将一个子类对象指针赋值给父类指针,对应的virtual函数会执行多态调用,析构函数亦同。反之,不期望作为基类的class,不应该声明virtual析构函数。

8. 别让异常逃离析构函数

如果在析构过程中出现了异常,将其往上层、即调用方传播是不明智的,因为只会导致析构没有正常结束,很有可能导致内存泄漏。我们应当尽量将可能抛出异常的操作放到成员函数中,并对异常进行处理

9. 绝对不在构造和析构过程中调用virtual函数

因为虚函数是为了让子类选择是否重写的成员函数,同时为该函数提供一个缺省实现;(纯虚函数是强制其继承体系中可实例化的子类必须实现)。所以,在构造函数中调用一个虚函数,这个虚函数只能映射到当前层级的class中,所以可能无法按照预期调用到子类实现的虚函数上去。(另一个角度,构造还未完成,所以还找不到虚函数表,所以无法完成多态调用)。

析构函数中调用虚函数也是十分危险的,假如你在子类析构函数开始调用,子类的成员便会变得未定义,执行完子类析构后,开始进入父类析构函数,这个析构函数中如果调用virtual函数,只会映射到父类的对应virtual函数上,并不会映射到你最初调用的那个子类的成员函数上,这种时候很容易发生纯虚函数被调用的报错,导致程序直接crash掉。

10. 令operator=返回一个reference to *this

我们写的每行代码,如果有很多操作符,按照优先级通过右结合律去匹配操作数。比如连续赋值,所以赋值操作也需要返回一个值去和次右操作数匹配。为实现连续赋值,赋值操作必须返回一个reference指向赋值操作符左侧实参。所以,对于class中的操作符重载函数,也需要返回一个reference to *this。这非必须,但很必要,也符合预期。

11. 在operator=中处理“自我赋值”

这个也不是很重要的准则,只是为了确保客户代码异常调用引发不可预料的结果。目的主要还是要保证对象拷贝时的异常安全性,所以在实现每个成员拷贝前,通常加一个“证同测试”是明智之举。此外,利用copy-and-swap技术,可以保证异常安全性,先声明拷贝赋值传参方式为by value,那么可以构造一个右操作数的副本,然后将其与左操作数交换内容,最后返回左操作数的引用,右操作数是临时对象会自动销毁。

12. 复制对象时勿忘其每一部分

OOP中我们封装的类一般要实现两个copy函数,一个是拷贝构造,一个是拷贝赋值。首先,要明确拷贝操作的深浅,尤其是指针的拷贝,还有父类的成员拷贝也需要显式调用。最后,不能用拷贝赋值函数调用拷贝构造函数,反之也不行,行为无意义。这两个函数执行的目的基本一致,所以可能会存在重复代码,所以可将重复代码拎出到一个单独的成员函数来调用,以降低代码复杂度。

小结:以上。

《Effective C++》阅读总结(二):类的构造、析构和赋值的更多相关文章

  1. Effective C++笔记(二):构造/析构/赋值运算

    参考:http://www.cnblogs.com/ronny/p/3740926.html 条款05:了解C++默默编写并调用哪些函数 如果自定义一个空类的话,会自动生成默认构造函数.拷贝构造函数. ...

  2. C++ 类、构造析构、深拷贝

    1st,感性理解类的思想,就是把数据和对数据的操作打包在一块儿,设计类的时候要 想好数据部分和 要进行的操作.以下是时间类的示意,时间包含时分秒,Time为构造函数,该类支持的操作就是设置时间和读取时 ...

  3. 转:Delphi2010新发现-类的构造和析构函数功能

    Delphi2010发布了. 虽然凭着对Delphi的热爱第一时间就安装了,但是现在可能是年纪大了,对新事物缺乏兴趣了.一直都没有仔细研究. 今天有点时间试了一下新功能. 本来C#和Delphi.NE ...

  4. Delphi2010新发现-类的构造和析构函数功能

    Delphi2010发布了. 虽然凭着对Delphi的热爱第一时间就安装了,但是现在可能是年纪大了,对新事物缺乏兴趣了.一直都没有仔细研究. 今天有点时间试了一下新功能. 本来C#和Delphi.NE ...

  5. Effective C++ —— 构造/析构/赋值运算(二)

    条款05 : 了解C++默默编写并调用哪些函数 编译器可以暗自为class创建default构造函数.copy构造函数.copy assignment操作符,以及析构函数. 1. default构造函 ...

  6. 【原】SDWebImage源码阅读(二)

    [原]SDWebImage源码阅读(二) 本文转载请注明出处 —— polobymulberry-博客园 1. 解决上一篇遗留的坑 上一篇中对sd_setImageWithURL函数简单分析了一下,还 ...

  7. C++ 类 、构造、 析构、 重载 、单例模式 学习笔记及练习

    一.拷贝构造函数 1.是一种特殊的构造函数,就是用一个已有的对象去构造其同类的副本对象,即对象克隆. class 类名 { 类名(类名& that) { 对类成员挨个赋值 ... } } 练习 ...

  8. 《Effective C++》第2章 构造/析构/赋值运算(1)-读书笔记

    章节回顾: <Effective C++>第1章 让自己习惯C++-读书笔记 <Effective C++>第2章 构造/析构/赋值运算(1)-读书笔记 <Effecti ...

  9. Java语法专题1: 类的构造顺序

    合集目录 Java语法专题1: 类的构造顺序 问题 下面的第二个问题来源于Oracle的笔试题, 非常经典的一个问题, 我从07年开始用了十几年. 看似简单, 做对的比例不到2/10. 描述一下多级继 ...

随机推荐

  1. WordPress 网站开发“微信小程序“实战(二)

    原文链接:https://devework.com/wordpres...,转载请用明链注明来源,谢谢! 本文是"WordPress 开发微信小程序"系列的第二篇,本文记录的是开发 ...

  2. canvas 1px 出现模糊解决方法及原理

    关于canvas绘制1像素出现模糊的原因及解决方法 canvas是html5中非常强大的功能,但是在绘制的时候如果出现1像素,例如画一条1像素的线可能出现模糊情况. 一.解决方法 网上比较常见的解决方 ...

  3. 支付宝小程序中“<”号写法

    今天遇到一个小问题,记录一下 "<"号在h5页面都是可以直接显示的,但是在运行支付宝小程序时报错,找了一个解决办法 <text> {{char_lt}} 18.5 ...

  4. ABP源码分析 - 约定注册(2)

    比较随意,记录下过程,以便忘了以后重拾. 所谓约定注册是指不需要明确写代码注入,只需要按约定规则写服务类,框架自动完成服务注册. 例如,只要这样写,框架就会自动注册. public class Tax ...

  5. 入行数字IC验证的一些建议

    0x00 首先,推荐你看两本书,<"胡"说IC菜鸟工程师完美进阶>(pdf版本就行)本书介绍整个流程都有哪些岗位,充分了解IC行业的职业发展方向.<SoC设计方法 ...

  6. mpvue下拉刷新

    1 开启下拉刷新 在想要下拉刷新的页面的 main.json 里,添加: { "navigationBarTitleText": "页面标题", "e ...

  7. python---virtualenv创建管理虚拟环境

    virtualenv创建虚拟环境 安装包virtualenv pip install virtualenv 常用命令 # 为项目创建虚拟环境 cd project_dir virtualenv env ...

  8. pycharm的安装指导教程以及破解

    第一步:下载 下载网址:https://www.jetbrains.com/pycharm/download/#section=windows 根据自己的操作系统选择,然后点击download就开始下 ...

  9. JAVA 进程线程详解

    线程和进程 一.进程 进程是指运行中的程序,比如我们使用QQ,就启动该进程分配内存空间. 进程是程序的一次执行过程,或是正在运行的一个程序.是一个动态的过程:有它自升的产生,存在和消亡的过程 二.线程 ...

  10. 快速排序算法 - go实现

    在分析redis集群中大Key的时候,通常都采用分析rdb文件的方式:但是这种方式需要在每一台redis服务器上部署分析程序及分析脚本,而像salt之类的工具运维没有开放给我们使用,一台一台部署不好管 ...