《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 app)的一些总结
关于个人开源项目(vue app)的一些总结 项目地址 https://github.com/BYChoo/record 项目简介 此项目名叫:Record.是以Vue全家桶(vue,vue-rout ...
- ES6-11学习笔记--数值的扩展
二进制 0B 八进制 0O Number.isFinite() , Number.isNaN() Number.parseInt() , Number.parseFloat() Number ...
- spring-注入集合对象
1.创建Stu类 package com.spring.collections; import java.util.Arrays; import java.util.List; import java ...
- 帝国cms发布文章对哪些数据表做了操作
帝国cms 发布一篇文章会影响哪些数据表 insert into phome_enewsfile_1(pubid,filename,filesize,adduser,path,filetime,cla ...
- RPC及Dubbo和ZooKeeper的安装
RPC及Dubbo和ZooKeeper的安装 RPC 通信有两种方式:HTTP(无状态协议,通信协议),RPC(远程过程调用) 它两的本质没有区别,只是功能有点不一样 官方解释: RPC是指远程过程调 ...
- [资源] 桃宝上十几块买的C#教程网盘
我粗略的看了下觉得挺好的,分享给大家 链接:https://pan.baidu.com/s/1iHuLUXde4_L7NB-Zw9JWNg 提取码:1314
- toggleClass() 把本来的有的类名去掉 本来没有的 加上
连续点击按钮可以交替颜色,就是改变class
- 使用Camera API https://developer.mozilla.org/zh-CN/docs/Web/Guide/API/Camera
使用Camera API 在本文章中 获取到所拍摄照片的引用 在网页中展示图片 完整的示例代码 HTML页面: JavaScript文件: 浏览器兼容性 通过Camera API,你可以使用手机的摄像 ...
- Windows 下 MSYS2 环境配置和 MinGW-w64 C++ 环境配置
Windows 下 MSYS2 环境配置和 MinGW-w64 C++ 环境配置 1.简介 本文主要是 Windows 下 MSYS2 环境配置和 MinGW-w64 C++编译环境配置方法 2.下载 ...
- Primitive Primes - 题解【数学】
题面 It is Professor R's last class of his teaching career. Every time Professor R taught a class, he ...