《Effective C++中文版,第三版》读书笔记5

条款26:尽可能延后变量定义式出现时间

原因:

​ 只要你定义了一个变量而其类型带有一个构造和一个析构,程序控制流到达其定义时有构造成本,控制流离开该变量的作用域时有析构成本

尽可能延后

不只因该延后变量的定义,直到非得使用该变量的前一刻为止,甚至应该尝试延后这份定义直到能够给它初值实参为止。

只在循环内使用的变量

A:定义于循环外

B:定义于循环内

两种情况使用A
1.赋值成本比‘’构造+析构‘成本低

​ 2.正在处理代码中效率高度敏感的部分

其它情况请使用B方法

条款27:尽量少做转型动作

旧式转型

​ (T) expression T(expression)

新式转型

​ const_cast_expression()/dynamic_cast(expression)/reinterpret_cast(expression)/static_cast_(expression)

四种新式转型简介:

​ const_cast通常被用来移除对象的常量属性,也是唯一由此能力的C++转型操作符

​ dynamic_cast主要是用来执行“安全向下转型”,也就是用来决定某对象是否归属继承体系中的某个类型。唯一一个无法用旧式转型执行的动作,也是唯一可能耗费重大运行成本的转型动作

​ reinterpret_cast意图执行低级转型,实际动作(即结果)可能取决于编译器,这也表示它不可移植

​ static_cast用来强迫隐式转换,将non-const->const, int->double,void*->type*,pointer-to-base->pointer-to-derived,但是无法从const->non-const

旧的风格任然合法,但是新的更受欢迎:

​ 1.新的风格容易在代码中被辨识出来

​ 2.各转型动作的目标愈窄化,编译器愈可能诊断出错误的运用。

何时使用旧式转型?

唯一的时机是,当我们调用一个explicit构造函数将一个对象传递给一个函数时。

任何一个类型转化(显式的还是隐式的)往往真的令编译器编译出运行期间执行的码

单一对象可能拥有一个以上的地址么?

​ 以base_执行它的时的地址和以dervied_指向它时的地址

​ C++中可能,多重继承几乎一直发生,单一继承可能发生

dynamic_cast的许多实现版本执行速度相当慢

什么情况下可能会使用dynamic_cast?

​ 通常是因为你想在一个你 认定为derived class对象身上执行derived class操作函数,但你手上只有一个”指向base“的pointer或reference

​ 在这种情况下如何避免使用dynamic_cast?

​ 1.使用容器并在其中存储直接指向derived class对象的指针

​ 2.在base class内提供virtual函数做你想对各个派生类做的事(其实就是利用动态绑定机制–个人看法)

请记住:

​ 如果可以,尽量避免转型,特别是在注重效率的代码中避免dynamic_casts.

​ 如果转型是必须的,那么请将它隐藏于某个函数背后。客户可以调用该函数,而不需要将转型代码放进他们自己的代码

​ 宁可使用C+±stype(新式)转型,不要使用旧式转型。新式转型很容易辨识出来,而且也有着分门别类的功能

条款28:避免返回handles指向对象内部成分

原因:

​ 指向内部成分的handle的寿命可能比对象长,意味着一旦对象被析构,那么那个handle就变成空悬、虚吊。

两个小知识点:

​ 1.成员变量的封装性最多只能等于”返回其reference“的函数的访问级别

​ 如果一个public成员函数返回了一个私有成员变量的reference,那么这个私有成员变量看起来是私有的(它被声明为私有),但是实际在类外也能访问(它的reference被返回)

​ 2.如果const成员函数传出一个reference,后者所指数据与对象自身有关联,而它又被存储于对象之外,那么这个函数调用这可以修改那笔数据。

reference、指针和迭代器统统都是所谓的handles(号码牌,用来取得某个对象),返回一个代表对象内部数据的handle,随之而来的便是降低对象封装性的风险

小知识点:

​ 不被公开使用的成员函数(也就是被声明为protected或private)也是对象的内部的一部分

不是绝对,operator[]返回了reference指向容器内的数据,这些数据会随着容器被销毁而销毁

请记住:

​ 避免返回handles(reference、指针、迭代器)指向对象内部。

写一段体验一下:

class MyBase
{
public:virtual ~MyBase() = default;virtual void baseCout(){std::cout << "I am base" << std::endl;}
};class MyDerived : public MyBase
{
public:MyDerived() {}MyDerived(int ina, int inb) : a(ina), b(inb) {}virtual void baseCout(){std::cout << "I am Dervied" << std::endl;}void printAllMember(){std::cout << "a = " << a << ", b = " << b << std::endl;}// int &getA() const {return a;} //这个版本无法通过编译  binding reference of type 'int&' to 'const int' discards qualifiersconst int &getA() const { return a; }private:int a;int b;
};int main(int argc, char const *argv[])
{MyDerived *myderived = new MyDerived(11, 23);myderived->printAllMember();int &aaa = const_cast<int &>(myderived->getA());   // 换个花样,去掉其const属性std::cout << "&aaa 0 =======" << aaa << std::endl; // 这个时候值就是成员a的值aaa = 12312312;                                    // 修改myderived->printAllMember();                       // 从打印结果来看,对象内部的值已经被修改delete myderived;std::cout << "&aaa 1 =======" << aaa << std::endl; // 这个时候已经变成了随机值return 0;
}
// 输出结果
// a = 11, b = 23
// &aaa 0 =======11
// a = 12312312, b = 23
// &aaa 1 =======1507664

条款29:为“异常安全”而努力是值得的

异常安全函数提供三种保证之一:

基本承诺:

​ 如果异常抛出,程序内的任何事物仍然保持在有效状态下。没有任何对象或数据结构会因此而败坏,所有对象都处于一种内部前后一致的状态。

强烈保证:

​ 如果异常抛出,程序状态不改变。调用这样的函数需要有这样的认知,如果函数成功,就是完全成功,如果函数失败,程序会恢复到”调用之前“的状态。

不抛掷保证:

​ 承诺绝不抛出异常,因为它们总是能够完成它们原先承诺的功能。内置类型身上的所有操作都提供nothrow保证

实际:

​ 可能的话请提供nothrow保证,但对大部分函数而言,抉择往往落在基本保证和强烈保证之间。

请记住:

​ 异常安全函数即使发生异常也不会泄漏资源或允许任何数据结构败坏。这样的函数区分为三种可能的保证:基本型,强烈性,不抛异常型

​ 强烈保证,可以通过copy-and-swap实现出来,但是并非对所有函数都可实现或具备现实意义

​ 函数提供的异常安全保证,通常最高等于其所调用的各个函数的异常安全保证最弱者。

条款30:透彻了解inling的里里外外

inline函数的优点:看起像函数,动作像函数,比宏好,可以调用但是没有函数调用所招来的额外开销。

关键知识点:

​ inline只是对编译器的一个申请,不是强制命令。这个申请可以显式或隐式

​ 显式: 使用inline关键字

​ 隐式:将函数定义于class定义式中

习惯:

​ inline函数通常别置于头文件中。

请记住:

​ 将大多数inlining限制带小型、被频繁调用的函数身上。

​ 不要因为function templates出现在头文件中,就将其声明为inline

条款31:将文件间的编译关系降至最低

简单的设计策略:

​ 如果使用object references 或object points可以完成任务,就不要使用objects. 可以只靠一个类型声明就定义出指向该类型的references和pointers.但如果定义某个类型的objects,就需要用到该类型的定义式

​ 如果能够,尽量以class声明替换class的定义式子。注意,当你声明一个函数而它用到某个class时,你并不需要class的定义;即便是使用by value方式传递参数(或返回值)也一样。

为声明式和定义式提供不同的头文件

声明式的头文件命名”功能fwd.h“,举例:_<_iosfwd>内含iostream个组件的声明式

请记住:

​ 支持编译依存性最小化的一般构想是:相依于声明式,不要相依于定义式。基于此构想的两个手段是Handle classes 和interface classes

​ 程序库头文件应该以”完全且仅有声明式“的形式存在。这种做法不论是否设计templates都适用。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/51720.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

CAD泰森多边形框架3D插件

插件介绍 CAD泰森多边形框架3D插件可用于在AutoCAD软件内生成三维Voronoi框架结构实体模型&#xff0c;适用于多孔Voronoi科研论文渲染绘图、Voronoi框架有限元建模、Voronoi空间结构优化等方面的应用。 使用说明 插件可设置生成的几何尺寸、晶格尺寸及边框直径等信息。 插…

Java中字符串拼写常用方法和高级技巧,举例并说明,加上注释和实际运行效果说明

Java中字符串拼写常用方法和高级技巧&#xff0c;举例并说明&#xff0c;加上注释和实际运行效果说明 目录 1、使用""操作符拼接字符串 2、使用StringBuilder类拼接字符串 3、使用String.format()方法格式化字符串 4、使用String.concat()方法拼接字符串 5、使…

SpringBoot上传文件的实现与优化

一、什么是文件上传&#xff1f; 文件上传是指客户端将本地的文件通过HTTP协议发送到服务器端的过程。文件上传是Web开发中常见的功能之一&#xff0c;例如用户可以上传头像、照片、视频、文档等各种类型的文件。文件上传涉及到客户端和服务器端的交互&#xff0c;需要考虑文件…

学习 Java 报表技术导入 Maven 依赖出错:jacob 无法下载、jasperreports 依赖错误

发生缘由 最近在做一个可视化项目&#xff0c;用到了 Java 报表技术。在跟着「黑马」课程导入 pom.xml 文件的时候提示下载依赖错误。 com.jacob 包无法下载Failed to read artifact descriptor for com.lowagie:itext:jar:2.1.7.js6 运行环境 电脑系统版本&#xff1a;Win…

发现一种增加在 GitHub 曝光量的方法,已举报

今天偶然看到一种增加项目和个人在 GitHub 曝光量的方法&#xff0c;但感觉无法赞同这种做法&#xff0c;已经向 GitHub 官方举报。 具体怎么回事呢&#xff1f;我上周在 Vim 插件大佬 tpope 的一个项目提了个 Issue&#xff0c;但一周过去了&#xff0c;大佬也没有回应&#x…

【笔记】岂不怀归:三和青年调查

三和青年的遭遇绝非孤例&#xff0c;他们是中国现代化和城市化进程中一些难以被城市容纳的群体的缩影。三和青年的“后备军”&#xff0c;是整整一代没有知识与技能的农村青年。本书对三和青年抱以人道主义的关怀与同情&#xff0c;并鼓励各界关注社会发展过程中被抛下的那一群…

CSDN编程题-每日一练(2023-08-25)

CSDN编程题-每日一练&#xff08;2023-08-25&#xff09; 一、题目名称&#xff1a;影分身二、题目名称&#xff1a;小鱼的航程(改进版)三、题目名称&#xff1a;排查网络故障 一、题目名称&#xff1a;影分身 时间限制&#xff1a;1000ms内存限制&#xff1a;256M 题目描述&am…

Git gui教程---第八篇 Git gui的使用 创建一个分支

一般情况下一个主分支下代码稳定的情况下会新建出一个分支&#xff0c;然后在分支上修改&#xff0c;修改完成稳定后再合并到主分支上。 或者几个人合作写一份代码&#xff0c;每个人各一个分支&#xff0c;测试稳定再合并到主分支上。 在git gui选择菜单栏“分支”&#xff0…

蓝桥杯上岸每日N题 (交换瓶子)

大家好 我是寸铁 希望这篇题解对你有用&#xff0c;麻烦动动手指点个赞或关注&#xff0c;感谢您的关注 题目描述 有 N 个瓶子&#xff0c;编号 1∼N&#xff0c;放在架子上。 比如有 5 个瓶子&#xff1a; 2 1 3 5 4 要求每次拿起 2 个瓶子&#xff0c;交换它们的位置。 …

android adb自动连接手机安装apk bat

1.新建bat文件adb echo off:apk文件名称 在setting.txt获取 set apkFileName"":设置文件 set settingFileE:\apk\bat\setting.txt:启动页面 applicationid/启动页面路径 set startActivitycom.aaa.aaa/com.aaa.aaa.ui.common.SplashActivity:读取settingFile第一行的…

【Java基础】 - 常用注解@SuppressWarings

Java基础 - 常用注解SuppressWarings 文章目录 Java基础 - 常用注解SuppressWarings一、概述二、 SuppressWarings注解使用2.1. 抑制单类型的警告2.2. 抑制多类型的警告2.3. 抑制所有类型的警告 四、注解目标五、抑制警告的关键字 一、概述 java.lang.SuppressWarnings是J2SE5…

什么是代码审计?怎么做?

代码审计是对源代码进行人工或自动化审查&#xff0c;以查找潜在的安全漏洞和隐患。在信息安全测试中&#xff0c;代码审计是非常重要的一环。它主要包括以下几个方面&#xff1a; 1.变量验证&#xff1a;检查代码是否对变量进行验证&#xff0c;防止变量被恶意用户篡改。 2.…

板卡设计+硬件每日学习十个知识点(44)23.8.24 (检测单元设计,接口部分设计,板卡电源输入设计,电源检测电路)

文章目录 1.检测单元介绍&#xff08;使用GD32单片机&#xff09;2.GD32的最小系统板3.GD32的温度监测4.GD32的电压监测和电流监测5.GD32的布线6.接口部分设计7.板卡电源输入设计8.电源检测电路 1.检测单元介绍&#xff08;使用GD32单片机&#xff09; 答&#xff1a; 首先要为…

Forrester首次面向中国的开源报告:阿里云在云原生领域开源布局最全面

Forrester 于近期发布了《Navigate The Cloud-Native Ecosystem In China, 2023》&#xff0c;报告概述了中国云原生领域的开源项目对构建云原生生态的促进作用&#xff0c;这些开源项目正深刻影响着企业的技术决策者以何种策略拥抱云原生这一现代 IT 基础设施的核心。 报告表…

很干的 Nginx

&#x1f3a8; 前言 本篇文章有些概念性的东西&#xff0c;是结合自己的理解表达出来的&#xff0c;可能有些理解不到位的地方。希望多多指教&#xff0c;谢谢大家。 红包献上 &#x1f9e7;&#x1f9e7;&#x1f9e7;&#x1f9e7;&#x1f9e7;&#x1f9e7;&#x1f9e7;…

Android Camere开发入门(2):Camera2的使用

Android Camere开发入门(2):Camera2的使用 Camera2 API简介 在上一篇文章《Android Camere开发入门(1):Camera1的使用》中,我们了解了如何在Android应用中使用Camera API来访问设备的摄像头。然而,随着Android设备的发展和硬件的提升,我们需要使用更强大、更灵活的API…

5.7 汇编语言:汇编高效乘法运算

乘法指令是一种在CPU中实现的基本算术操作&#xff0c;用于计算两个数的乘积。在汇编语言中&#xff0c;乘法指令通常是通过mul&#xff08;无符号乘法&#xff09;和imul&#xff08;有符号乘法&#xff09;这两个指令实现的。由于乘法指令在执行时所消耗的时钟周期较多&#…

深度学习处理文本(NLP)

文章目录 引言1. 反向传播1.1 实例流程实现1.2 前向传播1.3 计算损失1.4 反向传播误差1.5 更新权重1.6 迭代1.7 BackPropagation & Adam 代码实例 2. 优化器 -- Adam2.1 Adam解析2.2 代码实例 3. NLP任务4. 神经网络处理文本4.1 step1 字符数值化4.2 step 2 矩阵转化为向量…

成集云 | 抖店连接器客户静默下单催付数据同步钉钉 | 解决方案

源系统成集云目标系统 方案介绍 随着各品牌全渠道铺货&#xff0c;主播在平台上直播时客户下了订单后不能及时付款&#xff0c;第一时间客户收不到提醒&#xff0c;不仅造成了客户付款率下降&#xff0c;更大量消耗了企业的人力成本和经济。而成集云与钉钉深度合作&#xff0…

STM32--USART串口

文章目录 通信接口串口通信硬件电路电平标准参数时序 USART主要特性框图 数据帧发送器 波特率发生器SWART串口发送与接收工程串口收发数据包 通信接口 通信接口是指连接中央处理器&#xff08;CPU&#xff09;和标准通信子系统之间的接口&#xff0c;用于实现数据和控制信息在不…