读书笔记:《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…...
基于算法竞赛的c++编程(28)结构体的进阶应用
结构体的嵌套与复杂数据组织 在C中,结构体可以嵌套使用,形成更复杂的数据结构。例如,可以通过嵌套结构体描述多层级数据关系: struct Address {string city;string street;int zipCode; };struct Employee {string name;int id;…...

AI-调查研究-01-正念冥想有用吗?对健康的影响及科学指南
点一下关注吧!!!非常感谢!!持续更新!!! 🚀 AI篇持续更新中!(长期更新) 目前2025年06月05日更新到: AI炼丹日志-28 - Aud…...

业务系统对接大模型的基础方案:架构设计与关键步骤
业务系统对接大模型:架构设计与关键步骤 在当今数字化转型的浪潮中,大语言模型(LLM)已成为企业提升业务效率和创新能力的关键技术之一。将大模型集成到业务系统中,不仅可以优化用户体验,还能为业务决策提供…...

零基础设计模式——行为型模式 - 责任链模式
第四部分:行为型模式 - 责任链模式 (Chain of Responsibility Pattern) 欢迎来到行为型模式的学习!行为型模式关注对象之间的职责分配、算法封装和对象间的交互。我们将学习的第一个行为型模式是责任链模式。 核心思想:使多个对象都有机会处…...
【C++从零实现Json-Rpc框架】第六弹 —— 服务端模块划分
一、项目背景回顾 前五弹完成了Json-Rpc协议解析、请求处理、客户端调用等基础模块搭建。 本弹重点聚焦于服务端的模块划分与架构设计,提升代码结构的可维护性与扩展性。 二、服务端模块设计目标 高内聚低耦合:各模块职责清晰,便于独立开发…...

使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台
🎯 使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台 📌 项目背景 随着大语言模型(LLM)的广泛应用,开发者常面临多个挑战: 各大模型(OpenAI、Claude、Gemini、Ollama)接口风格不统一;缺乏一个统一平台进行模型调用与测试;本地模型 Ollama 的集成与前…...
LeetCode - 199. 二叉树的右视图
题目 199. 二叉树的右视图 - 力扣(LeetCode) 思路 右视图是指从树的右侧看,对于每一层,只能看到该层最右边的节点。实现思路是: 使用深度优先搜索(DFS)按照"根-右-左"的顺序遍历树记录每个节点的深度对于…...
音视频——I2S 协议详解
I2S 协议详解 I2S (Inter-IC Sound) 协议是一种串行总线协议,专门用于在数字音频设备之间传输数字音频数据。它由飞利浦(Philips)公司开发,以其简单、高效和广泛的兼容性而闻名。 1. 信号线 I2S 协议通常使用三根或四根信号线&a…...

Kafka入门-生产者
生产者 生产者发送流程: 延迟时间为0ms时,也就意味着每当有数据就会直接发送 异步发送API 异步发送和同步发送的不同在于:异步发送不需要等待结果,同步发送必须等待结果才能进行下一步发送。 普通异步发送 首先导入所需的k…...

Proxmox Mail Gateway安装指南:从零开始配置高效邮件过滤系统
💝💝💝欢迎莅临我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:「storms…...