读书笔记:《More Effective C++》
More Effective C++
Basics
reference & pointer
- reference 必定有值,pointer 可以为空
- reference 声明时必须定义,必须初始化
- reference 无需测试有效性,pointer 必须测试是否为 null
- reference 可以更改指向对象的值,但是无法指向其他对象,pointer 可以指向其他对象
cast
- c 转型:(type)expr
- c++ 转型:cast(expr)
- static:just like c 转型,无类型检查
- dynamic:base-》derived,有类型检查
- reinterpret:二进制重新解释,受制于编译期平台
- const:amend costness or volatileness
polymorphically array
- 使用base array pointer处理derived array,会导致未定义行为
default constructor
- 贸然提供default constructor需要在运行时测试是否值有效
- 缺乏default constructor会带来束缚
- 无法创建对象数组,只能创建指针数组
- 可以使用 placement new 创建对象数组,显式使用析构函数的 placement delete删除
- 使用 delete 删除 placement new 创建的对象会导致未定义行为
Operators
implicit conversion
- 单参数构造函数(或其余参数有默认值)
- 隐式类型转换操作符
- 隐式类型转换导致难以发现的问题:
- 构造函数标记为 explicit
- 定义显式类型转换:asType()
- 只能进行一次隐式转换,多次类型转换不会有问题
increment/decrement & prefix/postfix
- 【++i,累加后取出】:clazz& operator++()
- 返回引用,允许++++i
- 【i++,取出后累加】:const clazz operator++(clazz)
- 额外参数区分,参数不得使用
- 返回const,不允许i++++
- 为了使得逻辑一致,用increment prefix来实现increment postfix
override &&、||、,
- 重载&&、||导致问题:
- &&、||,条件满足/不满足会提前终止
- 重载后,左右式作为函数参数都会被执行
- 重载,导致问题:
- 逗号表达式,先求解左式,再求解右式,值为右式
- 重载后,函数无法保证执行顺序
new, operator new, placement new, delete, operator delete, []
- new:无法重载,operator new + constructor + placement new
- operator new:重载分配内存的行为
- void * operator new(size_t)
- placement new:重载在指定内存上构建对象
- void * operator new(size_t, void* location)
- delete:destructor + operator delete
- placement new 分配的内存无法通过 operator delete 删除
- 显式析构 + 分配内存对应的方式删除
- new->delete
- malloc->free
- 显式析构 + 分配内存对应的方式删除
- placement new 分配的内存无法通过 operator delete 删除
Exceptions
- 程序运行出错时设置状态变量或返回错误码,无法保证异常被程序处理,程序可能会异常运行;而抛出异常如果未进行捕获,程序便会立刻终止。
delete in destructor
- 将资源分配在对象内,在析构函数中删除内存
- 析构函数必然会被调用,防止因为异常产生未删除内存
exceptions in constructor
- 构造函数异常,部分构造的对象不会自动析构
- 将所有成员变量视为RAII对象,使用shared_ptr
exceptions in destructor
- 使用uncaught_exception判断析构函数时候正有一个exception在作用中
- 正在处理异常的析构函数抛出未捕获的异常,会导致程序终止
- 不应该让析构函数抛出异常,析构函数应该是异常安全的
stack unwinding
C++异常处理,栈展开机制:
- 异常被抛出
- 当前作用域,搜索异常处理程序catch块
- 未搜索到,销毁该作用域内的局部对象
- 调用析构函数出现异常,程序终止,std::terminate
- 退出当前作用域,继续搜索上一级作用域
- 未处理异常,std::terminate,std::abort,生成核心转储文件
catch exceptions param pass
- 处理异常和函数传参的区别
- 异常永远会被复制,因为异常处理程序超出函数调用作用域
- 按值捕获,复制两次,传参一次,复制一次
- 引用捕获,复制一次
- 不发生隐式类型转换,仅能发生继承类型转换
- 异常按catch的顺序处理,没有最优类型匹配
- 子类异常应该写在基类异常的前面,否则不会被处理
- 异常永远会被复制,因为异常处理程序超出函数调用作用域
catch exceptions by reference
- catch by pointer:无法判断是否应该删除资源
- catch by value:子类异常由基类捕获会导致对象切割,仅剩下基类行为
- catch by reference:推荐使用,且仅复制一次
exception specifications
- 在定义中指定函数可能抛出的异常
- 未指定则表明可能抛出任何异常
- 指定noexcept表明不会抛出任何异常
- 抛出未定义异常会导致unexpected函数调用
- unexpected的默认行为是调用terminate
- 可以使用set_unexpected自定义处理行为
- 可以提供额外的异常定义说明,但是违反说明的异常会直接导致程序终止
exception handling cost
- 异常处理会使得程序效率下降5%~10%
Efficiency
80-20 rule
- 80%的资源被20%的代码占用,不仅需要大幅优化代码,更重要的是找到那20%的瓶颈
- 不根据经验和直觉,而是使用profiler来分析那20%代码
lazy evaluation
- 如果计算不是绝对必要,使用lazy evaluation替代eager evaluation
over-eager evaluation
- cache:缓存已计算的值
- prefetch:预先从磁盘读取可能访问的值,每次读取磁盘多于请求量的值
avoid temporary
- 临时对象≠局部对象,临时对象是没有名字的栈对象
- 函数传参,隐式类型转换
- by value:隐式转换为临时对象
- by const reference:隐式转换为临时对象
- by non-const reference:隐式转化无法被触发,因为对临时对象的修改无法反馈会引用对象,因此编译报错
- 函数返回值
- 使用+=替代+
- 返回值优化RVO
- 函数传参,隐式类型转换
return value optimize
- 直接返回构造函数,避免临时对象的生成
overload to avoid implicit type conversions
- 使用函数重载来避免没有函数重载时的隐式类型转换
supply += and +
- 操作符+=往往比+有更高的效率
- 重载操作符的时候提供+=版本
third party library
- 相同功能的第三方库,在性能方面,可能会有不同的设计,和不同的效率偏重
inherit cost
- virtual functions:
- 每个class包含一个虚函数表
- 每个对象包含一个虚函数表的指针
- virtual 函数无法 inline,因为 inline 需要在编译期复制函数调用,而 virtual 需要运行期才能确定调用函数
- multiple inheritance & virtual base classes
- 菱形继承需要virtual base class,额外的指针开销
- runtime type identification,RTTI
- typeid获取class相应的type_info,需要额外的指针指向type_info
- 可以在虚函数表中添加指向type_info的指针
Techniques
virtual constructor & non-member function
- virtual constructor
- factory function 根据参数生成不同的子类
- virtual copy constructor
- 每个子类添加虚函数clone调用拷贝构造函数
- virtual non-member function
- 每个子类添加虚函数实现具体操作
- non-member function inline化,调用相应虚函数
limit class instance count
- 关键资源有限,其对应的类示例数目也有限
- 零或一:单例模式
- n:在构造函数中添加static示例计数,使用make函数显式构造,防止隐式构造增加计数
fore constructor in/out of heap
- in heap:对象有自杀能力,delete删除内存
- out of heap:对象不会造成内存泄漏
- 重载:
- static void * operator new(size_t)
- static void operator delete(void *)
smart pointers
- 智能指针无法在子类和基类之间转换,需要借助于隐式类型转换操作符
reference count
- 多数对象共享少数的实值,实值的产生和删除成本高,使用引用计数来记录共享对象的个数,在引用计数为零时删除
proxy class
- 表示一个观念上不存在的对象
- 实现[][]重载,proxy对象为Array1D
multi virtual function
- 根据多个子类的类型判断调用的函数
- func(base*, base*)
- 虚函数+RTTI,运行时类型辨识
- 虚函数重载
- 自行实现虚函数表
- func(base*, base*)
Miscellany
相关文章:

读书笔记:《More Effective C++》
More Effective C Basics reference & pointer reference 必定有值,pointer 可以为空reference 声明时必须定义,必须初始化reference 无需测试有效性,pointer 必须测试是否为 nullreference 可以更改指向对象的值,但是无法…...

手写VUE后台管理系统6 - 支持TS声明文件.d.ts
TS 使用声明文件进行类型定义。 配置 在 tsconfig.json 文件中,找到 include 属性,添加 "src/**/*.d.ts",表示 src 目录下的所有 .d.ts 文件都会被自动加载。 添加后内容如下 "include": ["src/**/*.ts",&…...

第八天:信息打点-系统端口CDN负载均衡防火墙
信息打点-系统篇&端口扫描&CDN服务&负载均衡&WAF防火墙 一、知识点 1、获取网络信息-服务器厂商: 阿里云,腾讯云,机房内部等。 网络架构: 内外网环境。 2、获取服务信息-应用协议-内网资产: FTP…...

一款充电桩解决方案设计
一、基本的概述 项目由IP6536提供两路5V 1.5A 的USB充电口,IP6505提供一路最大24W的USB快充口支持QC3.0 / DCP / QC2.0 / MTK PE1.1 / PE2.0 / FCP / SCP / AFC / SFCP的快充协议,电池充电由type-C输入经过IP2326输出最高15W快充对电池进行充电…...

Leetcode 2953. Count Complete Substrings
Leetcode 2953. Count Complete Substrings 1. 解题思路2. 代码实现 题目链接:2953. Count Complete Substrings 1. 解题思路 这一题麻烦的点就在于说有两个限制条件,但是好的点在于说这两个限制条件事实上是相互独立的。 因此,我们可以通…...

【Python-第三方库-pywin32】随笔- Python通过`pywin32`获取窗口的属性
Python通过pywin32获取窗口的属性 基础 获取所有窗口的句柄 【代码】 import win32guidef get_all_windows():hWnd_list []win32gui.EnumWindows(lambda hWnd, param: param.append(hWnd), hWnd_list)print(hWnd_list)return hWnd_list【结果】 获取窗口的子窗口句柄 【代…...

Flask使用线程异步执行耗时任务
1 问题说明 1.1 任务简述 在开发Flask应用中一定会遇到执行耗时任务,但是Flask是轻量级的同步框架,即在单个请求时服务会阻被塞,直到任务完成(注意:当前请求被阻塞不会影响到其他请求)。 解决异步问题有…...

zabbix监控nginx
zabbix是什么 web界面提供的一种可视化的监控服务软件 以分布式的方式系统监控以及网络监控,硬件监控等等开源的软件 zabbix的架构 1、c/s模式 客户端和服务端,zabbix server服务端 zabbix agent 客户端 2、通过B/S B是浏览器 S服务端,通…...

【CVE-2023-49103】ownCloud graphapi信息泄露漏洞(2023年11月发布)
漏洞简介 ownCloud owncloud/graphapi 0.2.x在0.2.1之前和0.3.x在0.3.1之前存在漏洞。graphapi应用程序依赖于提供URL的第三方GetPhpInfo.php库。当访问此URL时,会显示PHP环境的配置详细信息(phpinfo)。此信息包括Web服务器的所有环境变量&a…...

可视化数据库管理客户端:Adminer
简介:Adminer(前身为phpMinAdmin)是一个用PHP编写的功能齐全的数据库管理工具。与phpMyAdmin相反,它由一个可以部署到目标服务器的文件组成。Adminer可用于MySQL、PostgreSQL、SQLite、MS SQL、Oracle、Firebird、SimpleDB、Elast…...

Python----字典练习
相关链接:Python---字典的增、删、改、查操作_python中字典的增删改查-CSDN博客 Python---字典---dict-CSDN博客 Python---引用变量与可变、非可变类型-CSDN博客 重点: 字典中的 key (就是键)可以是很多数据类型(…...

CentOS 部署 WBO 在线协作白板
1)WBO 白板工具介绍 1.1)WBO 白板简介 WBO 是一个自由和开源的在线协作白板。它允许多个用户同时在一个虚拟的大型白板上画图。该白板对所有线上用户实时更新,并且状态始终保持。它可以用于许多不同的目的,包括艺术、娱乐、设计和…...

qt-C++笔记之QStringList
qt-C笔记之QStringList —— 杭州 2023-12-03 文章目录 qt-C笔记之QStringList1.1.《Qt官方文档》第一部分翻译:继承自QList\<QString\>-初始化-添加字符串1.2.迭代字符串1.3.join()和split()1.4.filter()1.5.lastIndexOf()1.6.indexOf()1.7.replaceInString…...

ply前端
ply 是 eBPF 的 front-end 前端工具之一,专为 embedded Linux systems 开发,采用 C 语言编写,只需 libc 和内核支持 BPF 就可以运行,不需要外部 kernel 模块,不需要 LLVM,不需要 python。 ply 由瑞典工程师…...

U盘不仅能在电脑上使用,在手机上也可使用,包括安卓和苹果手机,但苹果的较特殊
许多最好的安卓手机都使用USB-C端口在电脑上充电和来回传输文件,但如果你需要给老板发电子邮件的文件放在闪存驱动器或全尺寸SD卡上呢? 幸运的是,使用廉价的适配器电缆,你可以将USB加密狗或读卡器直接连接到手机上。你甚至可以直接使用USB-C闪存驱动器,以实现更轻松的过程…...

面试数据库八股文十问十答第二期
面试数据库八股文十问十答第二期 作者:程序员小白条,个人博客 相信看了本文后,对你的面试是有一定帮助的! ⭐点赞⭐收藏⭐不迷路!⭐ 1.MySQL的主从复制 MySQL的主从复制是什么?MySQL主从复制是一种常见的…...

【LeetCode】每日一题 2023_12_2 拼车(模拟/差分)
文章目录 刷题前唠嗑题目:拼车题目描述代码与解题思路学习大佬题解 刷题前唠嗑 LeetCode?启动!!! 题目:拼车 题目链接:1094. 拼车 题目描述 代码与解题思路 func carPooling(trips [][]int…...

网络和Linux网络_7(传输层)UDP和TCP协议(端口号+确认应答+超时重传+三次握手四次挥手)
目录 1. 重看端口号 1.1 端口号的概念 1.2 端口号的划分 2. 重看UDP协议 2.1 UDP协议格式 2.2 UDP的特点 3. 重看TCP协议 3.1 TCP协议格式 3.2 TCP的解包分用 3.3 TCP的可靠性及机制 3.3.1 确认应答ACK机制 3.3.2 超时重传机制 3.3.3 连接管理机制(三次…...

KALI LINUX安全审核
预计更新 第一章 入门 1.1 什么是Kali Linux? 1.2 安装Kali Linux 1.3 Kali Linux桌面环境介绍 1.4 基本命令和工具 第二章 信息收集 1.1 网络扫描 1.2 端口扫描 1.3 漏洞扫描 1.4 社交工程学 第三章 攻击和渗透测试 1.1 密码破解 1.2 暴力破解 1.3 漏洞利用 1.4 …...

2023-12-03-解决libxkbcommon库编译完后图像界面不能使用键盘
layout: post # 使用的布局(不需要改) title: Ubuntu修复 # 标题 subtitle: 解决libxkbcommon库编译完图形界面不能使用键盘 #副标题 date: 2023-12-03 # 时间 author: BY ThreeStones1029 # 作者 header-img: img/about_bg.jpg #这篇文章标题背景图片 c…...

vue el-table表格中每行上传文件(上传简历)操作
1、HTML中 <el-table :data"formInfo.userListDto" border stripe max-height"400"><el-table-column type"index" label"序号" width"50"> </el-table-column><el-table-column prop"realName&q…...

Python批量图像处理--图片重命名、图片旋转
图像批量重命名: 使用batch_rename_images函数实现对多个文件夹下面的图片进行重命名操作 先检查文件名的后缀,使用了.endswith()方法来判断文件名是否以.jpg、.png或.JPG结尾,判断是否为图片文件 然后构造新的文件路径new_filepath&#…...

第五天 用Python批量处理Excel文件,实现自动化办公
用Python批量处理Excel文件,实现自动化办公 一、具体需求 有以下N个表,每个表的结构一样,如下: 需要把所有表数据汇总,把每个人的得分、积分分别加起来,然后按总积分排名,总积分一致时ÿ…...

mybatis整合(手动添加jar包方式)
操作步骤 创建数据库 建立user表 放入数据 1、创建javaweb工程并添加Jar包 用到的jar包 junit 用于测试 mybatis框架:mybatis-3.5.9.jar mysql数据库:mysql-connector-java-8.0.28.jar 2、添加MyBatis核心配置文件 <?xml version"1.0"…...

leetcode - 矩阵区域和
1314. 矩阵区域和 - 力扣(LeetCode) 给你一个 m x n 的矩阵 mat 和一个整数 k ,请你返回一个矩阵 answer ,其中每个 answer[i][j] 是所有满足下述条件的元素 mat[r][c] 的和: i - k < r < i k, j - k < c …...

头歌JUnit单元测试相关实验进阶
JUnit是一个由 Erich Gamma 和 Kent Beck 编写的一个回归测试框架(regression testing framework),主要供 Java 开发人员编写单元测试。Junit在极限编程和重构中被极力推荐使用,因为它可以大大地提高开发的效率。 Junit的特性&…...

【kafka实践】11|消费位移提交
消费者位移 消费者位移这一节介绍了消费者位移的基本概念和消息格式,本节我们来聊聊消费位移的提交。 Consumer 需要向 Kafka 汇报自己的位移数据,这个汇报过程被称为提交位移(Committing Offsets)。因为 Consumer 能够同时消费…...

Mac卸载、安装Python
卸载 说明 对于删除 Python,我们首先要知道其具体都安装了什么,实际上,在安装 Python 时,其自动生成: Python framework,即 Python 框架;Python 应用目录;指向 Python 的连接。 …...

算法——滑动窗口
滑动窗口大致分为两类:一类是窗口长度固定的,即left和right可以一起移动;另一种是窗口的长度变化(例如前五道题),即right疯狂移动,left没怎么动,这类题需要观察单调性(即指针)等各方…...

带头双向循环链表:一种高效的数据结构
💓 博客主页:江池俊的博客⏩ 收录专栏:数据结构探索👉专栏推荐:✅cpolar ✅C语言进阶之路💻代码仓库:江池俊的代码仓库🔥编译环境:Visual Studio 2022🎉欢迎大…...