《Effective C++》阅读总结(二):类的构造、析构和赋值
今天是周六早上,但很不幸待会儿还是要去公司,本月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++》阅读总结(二):类的构造、析构和赋值的更多相关文章
- Effective C++笔记(二):构造/析构/赋值运算
参考:http://www.cnblogs.com/ronny/p/3740926.html 条款05:了解C++默默编写并调用哪些函数 如果自定义一个空类的话,会自动生成默认构造函数.拷贝构造函数. ...
- C++ 类、构造析构、深拷贝
1st,感性理解类的思想,就是把数据和对数据的操作打包在一块儿,设计类的时候要 想好数据部分和 要进行的操作.以下是时间类的示意,时间包含时分秒,Time为构造函数,该类支持的操作就是设置时间和读取时 ...
- 转:Delphi2010新发现-类的构造和析构函数功能
Delphi2010发布了. 虽然凭着对Delphi的热爱第一时间就安装了,但是现在可能是年纪大了,对新事物缺乏兴趣了.一直都没有仔细研究. 今天有点时间试了一下新功能. 本来C#和Delphi.NE ...
- Delphi2010新发现-类的构造和析构函数功能
Delphi2010发布了. 虽然凭着对Delphi的热爱第一时间就安装了,但是现在可能是年纪大了,对新事物缺乏兴趣了.一直都没有仔细研究. 今天有点时间试了一下新功能. 本来C#和Delphi.NE ...
- Effective C++ —— 构造/析构/赋值运算(二)
条款05 : 了解C++默默编写并调用哪些函数 编译器可以暗自为class创建default构造函数.copy构造函数.copy assignment操作符,以及析构函数. 1. default构造函 ...
- 【原】SDWebImage源码阅读(二)
[原]SDWebImage源码阅读(二) 本文转载请注明出处 —— polobymulberry-博客园 1. 解决上一篇遗留的坑 上一篇中对sd_setImageWithURL函数简单分析了一下,还 ...
- C++ 类 、构造、 析构、 重载 、单例模式 学习笔记及练习
一.拷贝构造函数 1.是一种特殊的构造函数,就是用一个已有的对象去构造其同类的副本对象,即对象克隆. class 类名 { 类名(类名& that) { 对类成员挨个赋值 ... } } 练习 ...
- 《Effective C++》第2章 构造/析构/赋值运算(1)-读书笔记
章节回顾: <Effective C++>第1章 让自己习惯C++-读书笔记 <Effective C++>第2章 构造/析构/赋值运算(1)-读书笔记 <Effecti ...
- Java语法专题1: 类的构造顺序
合集目录 Java语法专题1: 类的构造顺序 问题 下面的第二个问题来源于Oracle的笔试题, 非常经典的一个问题, 我从07年开始用了十几年. 看似简单, 做对的比例不到2/10. 描述一下多级继 ...
随机推荐
- 手把手教你从零写一个简单的 VUE--模板篇
教程目录1.手把手教你从零写一个简单的 VUE2.手把手教你从零写一个简单的 VUE--模板篇 Hello,我又回来了,上一次的文章教会了大家如何书写一个简单 VUE,里面实现了VUE 的数据驱动视图 ...
- java中如何创建自定义异常Create Custom Exception
9.创建自定义异常 Create Custom Exception 马克-to-win:我们可以创建自己的异常:checked或unchecked异常都可以, 规则如前面我们所介绍,反正如果是chec ...
- .NET程序设计实验一
实验一 语言基础 一.实验目的 1. 熟悉Visual Stido.NET 实验环境: 2. 掌握控制台程序的编写方法: 3. 掌握C#程序设计语言的语法基础: 4. 掌握控制语句和数组的使用. 二 ...
- 每天找回一点点之MD5加密算法
之前在做项目的时候用户密码都进行了MD5的加密,今天突然想起来了总结一下(●'◡'●) 一.MD5是什么? MD5信息摘要算法(英语:MD5 Message-Digest Algorithm),一种被 ...
- css设置图片根据最大边自适应
给新手的福利,还是记一下吧.......很简单 <div> <img src="1.jpg" alt=""> </div> ...
- java-GUI编程之AWT组件
AWT中常用组件 基本组件 组件名 功能 Button Button Canvas 用于绘图的画布 Checkbox 复选框组件(也可当做单选框组件使用) CheckboxGroup 用于将多个Che ...
- 第一阶段:Java基础之控制结构
1.顺序结构 按照顺序控制结构运行,即语句从上到下,从左到右 2.选择结构 if..else..语句 switch..case..语句 3.循环结构 while循环 do...while & ...
- Linux curl遇到错误curl: (3) Illegal characters found in URL
服务器上执行一个脚本,在linux新建的sh,把本地编辑器的内容粘贴到文件里. 结果执行的时候报错了. 问题就是 curl:(3)Illegal characters found in URL 看着一 ...
- 几个i的幂的累加公式1^2+2^2+3^2 2~5
1^2+2^2+3^2+--+n^2=n(n+1)(2n+1)/6 1^3+2^3+3^3+...+n^3=(1+2+3+...+n)^2 =[n(n+1)/2]^2 1^4+2^4+3^4+--+n ...
- 『现学现忘』Git基础 — 8、Git创建本地版本库
目录 1.Git版本库介绍 2.创建本地版本库 场景一:创建一个空的本地版本库. 场景二:项目中已存在文件时,创建该项目的本地版本库. 场景三:在GitHub网站上创建仓库,克隆到本地. 1.Git版 ...