当前位置: 首页 > news >正文

Effective C++快速复习

Effective C++快速复习

习惯 C++

01 视 C++ 为一个语言联邦:C、Object-Oriented C++、Template C++、STL

02 尽量以 const, enum, inline 替换 #define:其实是尽量以编译器替换预处理器比较好,因为 #define 只是简单的字符串匹配替换,编译器无法看到,不利于 debug,也容易出问题

03 尽可能使用 const:Rust 语言设计就是 const 作为默认语义,可以帮助编译器侦测出错误用法

04 确定对象被使用前已经被初始化:内置类型对象进行手动初始化,C++不保证初始化他们;尽量使用初始化列表来初始化

构造,析构,赋值

05 了解 C++ 默认编写了哪些函数:默认构造函数、默认拷贝构造函数、默认拷贝赋值操作符、默认移动赋值操作符、析构函数

06 可以明确拒绝编译器自动生成的函数:例如将相应函数声明为 private 且不予实现,例如 Boost 里边有个 uncopyable 类

07 为多态基类编写 virtual 函数:带有多态性质的基类应该声明 virtual 析构函数,或者说一个类只要带有 virtual 函数,就应该有 virtual 析构函数;

08 别让异常逃离析构函数:如果析构函数调用的函数可能抛出异常,那么析构函数就应该捕捉任何一场,不传播或者直接 abort ;如果客户需要对某个操作函数运行期间抛出的异常作出反应,那么类应当提供一个普通函数,instead of 析构函数,执行该操作

09 绝不在构造和析构过程中调用 virtual 函数:你以为你调用的是子类的 virtual 函数,实际上可能是父类的 virtual 函数。在基类构造和析构期间调用的 virtual 函数不可下降至派生类。

*10 令 operator= 返回一个 this 引用:为了实现连续赋值

11 在 operator= 中处理自我赋值:比较来源对象和目标对象的地址是否相同;包括如果操作一个大的对象里有若干个对象,也要分别考虑是否有自我赋值。

12 复制对象时勿忘其每一个成分:拷贝赋值操作符要覆盖所有成员变量以及基类的成分(例如直接调用基类的拷贝赋值操作符);但是不要在拷贝赋值操作符里调用拷贝构造函数,而是要把二者的共同点提取出来作为一个新的函数

资源管理

13 以对象管理资源:使用 RAII 和智能指针的技术防止资源泄露

14 资源管理类中小心 coping 行为:常见的 RAII class copying 行为是:抑制复制、使用引用计数法、一同复制底部资源、转移底部资源的所有权

15 在资源管理类中提供对原始资源的访问:因为 APIs 往往要求访问原始资源(raw resources);可以采用显式转换和隐式转换的方式,前者比较安全,后者方便用户使用

16 成对使用 new 和 delete 时要采取相同形式:就是在有没有带数组 [] 符号上,new 和 delete 必须要统一

17 以独立语句将 new 得到的对象放入智能指针:意思是智能指针的以一个原始指针作为参数的构造函数是 explicit 的,所以要主动将 new 得到的对象指针放入智能指针里。

设计与声明

18 让接口容易被正确使用、不易被误用:接口一致、与内置类型行为兼容;消除客户的资源管理责任

19 设计 class 犹如设计 type:考虑新的类型应当如何被创建和销毁、初始化和赋值有着怎样的差别、值传递和引用传递有什么差别、是否需要配合某个继承体系、是否需要类型转换、如何使用、是否真的需要一个新的 class

20 宁以 pass-by-reference-to-cont 替换 pass-by-value:前者更高效,并且在继承关系存在时还可以防止子类部分被切割掉;但对于内置类型、STL迭代器和函数对象,后者更加合适。

21 必须返回对象时,不要返回其 reference:local stack 对象在函数结束时就会被销毁,如果是 heap-allocated 对象也应该返回 pointer 而不是 reference

22 将成员变量声明为 private:protedted 并不必 public 更具有封装性;将成员变量全部声明为 private,可赋予客户访问数据的一致性、进行更细粒度的访问控制、允许约束条件得到保证,给类的编写者更加充分的实现弹性

23 宁以 non-member、non-friend 替换 member 函数:这样可以提高封装性、包裹弹性和机能扩充性,可以将这类 non- 函数与类放在同一个命名空间下。(可以这样理解:增加这些 non- 函数只会在原有的封装性下做事情,而增加 member 函数却有可能会暴露出新的访问权限)

24 若所有参数皆需类型转化,请为此采用 non-member 函数:令 class 支持隐式类型转换往往是个坏主意;例如设计一个新的数值类型,它的算数运算想要兼容原有的内置类型,就需要将这些 operator+ 等函数写成 non-member;

25 考虑写一个不抛出异常的 swap 函数:自己提供的 swap 成员函数效率更高;定义完一个 member swap,也应当提供一个 non-member swap(即特化 std::swap()),来方便使用;为用户定义的类型进行 std templates 全特化是好的,但是不要往 std 命名空间里加入全新的东西。

实现

26 尽可能延后变量定义出现的时间:要用了再来定义,而不要像一些老的代码一样在开头定义好所有需要用到的变量;这样程序更加清晰,而且效率也可能得到提升。

27 尽量少做 casting 动作:即使要类型转换,也用 C++ 的新式类型转换(static_cast、dynamic_cast、const_cast、reinterprete_cast),这样在代码中容易被识别,也方便编译器诊断出错误;注重效率的代码中尽量不要用 dynamic_cast;注意 reinterprete_cast 不可移植;

28 避免返回 handles 指向对象内部成分:handles 指 references、指针、迭代器等,这样可以增加封装性

29 注意异常安全:注意不泄露任何资源、不允许数据破坏

30 透彻了解 inlining 的里里外外:inline 更适合小型的、被频繁调用的函数上,也可使潜在的代码膨胀问题最小化,使程序的速度提升机会最大化。

31 将文件键的编译依存关系降至最低:能使用 object reference 或者 pointer 弯沉任务的,就不要使用 object;尽量用 class 声明式替换定义式;为声明和定义提供不同的源文件,头文件应当完全仅有声明式。

继承与面型对象设计

32 public 继承应当塑模出 is-a 关系:is-a 关系是说,子类是一种基类,比如苹果是一种水果

33 避免遮掩继承而来的名称:可以用 using 声明或者 forwarding functions 的技巧来使用父类中被遮掩的名称

34 区分接口继承和实现继承:成员函数的接口总是会被继承;

  • 声明 pure virtual 函数是为了让派生类只继承函数接口、而必须要自己实现这个函数;
  • 声明 impure virtual 函数的目的,是让派生类继承该函数接口,同时提供一个默认实现版本
  • 声明 non-virtual 函数是为了让派生类直接继承函数接口,并且提供强制性实现

35 考虑 virtual 函数以外的其他选择:例如可以用 non-vritual interface 实现 Template Method 模式、Function Pointer 或 std::function 实现 Stategy 模式、

36 绝不重新定义继承而来的 non-virtual 函数:正如 34 中所讲,这是为了提供一份强制性的实现。

37 绝不重新定义继承而来的缺省参数值:缺省参数值是静态绑定,如果派生类继承了一个带有缺省参数值的函数,那么一定不要改缺省参数值(可以直接不写)

38 通过复合塑模出 has-a 或 is-implemented-by:复合是指 composition

39 审慎地使用 private 继承:private 继承也是 is-implemented-by 的意思,比复合的级别更低,可以实现 EBO;

40 审慎地使用多重继承:多重继承可能会带来歧义,而且 virtual 继承会带来 overhead,当 virtual base class 不带任何数据,将是最具实用价值的情况。当然多重继承也有正当用途,例如 public 继承某个 interface class 的同时 private 继承某个协助实现的 class

模板与泛型编程

41 了解隐式接口和编译器多态:对于 template 而言,接口是隐式的,基于有效表达式,多态则是通过template 具现化和函数重载解析发生于编译期。

42 了解 typename 的双重意义:既可以用在模板参数声明时,和 class 一样的用法,又可以用在表示由模板参数得到的派生类型上,标识嵌套从属类型名称,告诉编译器这是个类型。

43 学习处理模板化基类内的名称:在 derived class template 内通过 this-> 来引用 base class template 内的成员名称

44 将与参数无关的代码抽离 templates:因非类型模板参数而造成的代码膨胀,往往可以通过以函数参数或者 class 成员变量替换 template 参数来消除;

45 运用成员函数模板接受所有兼容类型:如果声明 member templates 用于泛化拷贝构造动作或泛化赋值操作,还是需要声明正常的拷贝构造函数和赋值操作符

46 需要类型转换时请为模板定义非成员函数:当我们编写一个 class template,而它所提供的与此template相关的函数支持所有参数的隐式类型转换时,请将哪些函数定义为 class template 内部的 friend 函数(例如前面提到的定义一个新的数值类型)

47 使用 traits classes 表现类型信息:通过萃取其可以是类型相关信息在编译器可用,参考 STL 的 iterator 实现

48 认识模板元编程:是一种编程范式,可将工作从运行期移往编译器,更早实现错误侦测,具有更高的执行效率

定制 new 和 delete

49 了解 new-handler 的行为

  • 需要让更多内存可以被使用

  • 当前 new-handler 无法获取更多内存时,可以安装别的 new-handler 替换自己

  • 卸除 new-handler

  • 抛出 (派生自)bad_alloc 的异常

  • 不返回:通常调用 abort 或 exit

50 了解替换编译器的 new 和 delete 的合理时机:往往是为了获得非传统的行为

  • 用来检测运用上的错误:例如 new 成功而 delete 失败造成的内存泄漏
  • 强化效能:编译器提供的 new 和 delete 不适用于长时间执行的程序
  • 收集统计数据:用于调试、收集 heap 使用信息

51 编写 new 和 delete 时需固守常规

  • operator new 内应当含有一个无穷循环,并且不断尝试分配内存;如果无法满足内存需求,就应当调用 new-handler;能够处理 0B 的申请;
  • operator delete 在接受 null 指针时不要做任何事情;

52 写了 palcement new 也要写 placement delete

杂项讨论

53 不要轻忽编译器的警告:0 error 不是最终目标

54/55 熟悉 TR1、Boost 等标准程序库 :虽然很多东西现在 C++11 以后都有了

相关文章:

Effective C++快速复习

Effective C快速复习 习惯 C 01 视 C 为一个语言联邦:C、Object-Oriented C、Template C、STL 02 尽量以 const, enum, inline 替换 #define:其实是尽量以编译器替换预处理器比较好,因为 #define 只是简单的字符串匹配替换,编译…...

【华为OD机试真题JAVA】绘图机器的绘图问题

标题:绘图机器的绘图问题| 时间限制:1秒 | 内存限制:262144K | 语言限制:不限 绘图机器的绘图笔初始位置在原点(0,0) 机器启动后按照以下规则来进行绘制直线 1. 尝试沿着横线坐标正向绘制直线 直到给定的终点E 2. 期间可以通过指令在纵坐标轴方向进行偏移 off…...

GPT-4最震撼我的一点

昨天我看了一遍OpenAI发的视频和论文,最震撼我的并不是根据手绘草图生成HTML页面代码,因为草图太简单,对于复杂的有交互的界面,还不知道它的能力究竟如何,能不能生成准确的、清晰的代码,我再实验一下再给大…...

LeetCode-复制带随机指针的链表

题目描述: 给你一个长度为 n 的链表,每个节点包含一个额外增加的随机指针 random ,该指针可以指向链表中的任何节点或空节点。 构造这个链表的 深拷贝。 深拷贝应该正好由 n 个 全新 节点组成,其中每个新节点的值都设为其对应的…...

如何在Unity中实现AStar寻路算法及地图编辑器

文章目录AStar算法简介实现Node节点节点间的估价算法核心邻节点的搜索方式地图编辑器简介实现绘制地图网格障碍/可行走区域地图数据存储AStar算法 简介 Unity中提供了NavMesh导航寻路的AI功能,如果项目不涉及服务端它应该能满足大部分需求,但如果涉及服…...

线性代数之矩阵

一、思维导图二、矩阵及其运算1、矩阵的定义注:零矩阵:元素均为0 的矩阵,通常记作0m*n称为矩阵的类型。满足阶梯形矩阵 行简化的阶梯形矩阵即满足如下条件的矩阵: (1)阶梯形; (2)非零首元所在列其余元素均为0 ; (3) 非…...

【个人首测】百度文心一言 VS ChatGPT GPT-4

昨天我写了一篇文章GPT-4牛是牛,但这几天先别急,文中我测试了用GPT-4回答ChatGPT 3.5 和 Notion AI的问题,大家期待的图片输入也没有出现。 昨天下午百度发布了文心一言,对标ChatGPT,录屏无实机演示让百度股价暴跌。但是晚上百度就…...

基于STM32的ADC采样及各式滤波实现(HAL库,含VOFA+教程)

前言:本文为手把手教学ADC采样及各式滤波算法的教程,本教程的MCU采用STM32F103ZET6。以HAL库的ADC采样函数为基础进行教学,通过各式常见滤波的实验结果进行分析对比,搭配VOFA工具直观的展示滤波效果。ADC与滤波算法都是嵌入式较为…...

Redis高级篇

文章目录面试题库redis有哪些用法?redis单线程时代性能依然很快的原因?主线程和IO线程怎么协作完成请求处理的BigKey(重要)什么算是BigKey?怎么发现BigKey?怎么删除bigkey?bigkey生产调优缓存双…...

sess.close()这句话一般是干什么的,在代码中可以不加么?

sess.close()这句话是用于关闭TensorFlow会话对象的方法。 关闭会话对象可以释放资源,避免内存泄漏,以及清除图中的变量和操作。 在代码中是否可以不加这句话,取决于你是如何创建和使用会话对象的。如果你使用了with语句来创建和管理会话对…...

网络舆情监测处置平台,TOOM舆情如何做好舆情风险点及防控措施?

网络舆情监测处置平台是一个综合性的系统,旨在帮助企业、政府或其他组织有效地管理和处置网络舆情。从多个角度来分析该平台,我们可以考虑以下几个方面: 1,技术实现 网络舆情监测处置平台的技术实现是其核心,它通常采…...

百度文心一言对标 ChatGPT,你怎么看?

文心一言 VS ChatGPT接受不完美 期待进步里程碑意义文心一言初体验✔ 文学创作✔ 商业文案创作✔ 数理逻辑推算✔ 中文理解✔ 多模态生成写在最后何为文心?“文”就是我们中华语言文字中的文,“心”是希望该语言模型可以用心的去理解语言,用心…...

阿里笔试2023-3-15

太菜了,记录一下笔试题目,代码有更好解法欢迎分享。 1、满二叉子树的数量。 给定一颗二叉树,试求这课二叉树有多少个节点满足以该节点为根的子树是满二叉树?满二叉树指每一层都达到节点最大值。 第一行输入n表示节点数量&#xff…...

STM32:TIM定时器输出比较(OC)

一、输出比较简介 1、输出比较 OC(Output Comapre)输出比较输出比较可以通过比较CNT(时基单元)和CCR(捕获单元)寄存器值的关系,来对输出电平进行置1、置0或翻转的操作,用于输出一定频…...

HTTPS 加密协议

✏️作者:银河罐头 📋系列专栏:JavaEE 🌲“种一棵树最好的时间是十年前,其次是现在” 目录HTTPS"加密" 是什么HTTPS 的工作过程引入证书HTTPS http 安全层 (SSL) SSL 用来加密的协议,也叫 TLS …...

分布式锁和分布式事务

分布式锁 没有图形,只通过大量文字进行说明。分布式锁:redis分布式锁, zk分布式锁, 数据库做分布式锁 redis分布式锁 setnx key value ex 10 原子操作 AB两个线程减库存业务,假设库存是10 A线程获取锁,…...

RK3568平台开发系列讲解(驱动基础篇)I2C协议介绍

🚀返回专栏总目录 文章目录 一、I2C基本读写过程二、通讯的起始和停止信号三、数据有效性四、地址及数据方向五、响应沉淀、分享、成长,让自己和他人都能有所收获!😄 📢I2C的协议定义了通讯的起始和停止信号、数据有效性、响应、仲裁、时钟同步和地址广播等环节。 一、…...

HTML 音频(Audio)

HTML 音频(Audio) 声音在HTML中可以以不同的方式播放. 问题以及解决方法 在 HTML 中播放音频并不容易! 您需要谙熟大量技巧,以确保您的音频文件在所有浏览器中(Internet Explorer, Chrome, Firefox, Safari, Opera)和所有硬件上…...

什么是Vue

✅作者简介:CSDN一位小博主,正在学习前端,欢迎大家一起来交流学习🏆 📃个人主页:白月光777的CSDN博客 🔥系列专栏:Vue从入门到进阶 💬个人格言:但行好事&…...

python 内置函数和多线程

以下是Python的一些内置函数。这些函数是Python语言提供的基本功能,可以在不需要导入任何其他模块的情况下直接使用。这些函数可以完成广泛的任务,例如数学运算,序列和集合操作,类型转换,文件操作等等。透彻理解这些函…...

【Spring】我抄袭了Spring,手写一套MySpring框架。。。

这篇博客实现了一个简单版本的Spring,主要包括Spring的Ioc和Aop功能 文章目录这篇博客实现了一个简单版本的Spring,主要包括Spring的Ioc和Aop功能🚀ComponentScan注解✈️Component注解🚁在spring中ioc容器的类是ApplicationConte…...

vue中的生命周期

前言 很多时候我们希望能在 vue 生命周期的过程中执行一些操作,生命周期钩子函数也因此诞生了。相信使用过 vue 框架的同学都知道,生命周期的钩子函数允许我们在实例的不同阶段执行各种操作,便于我们更好的控制和使用实例。 生命周期钩子函数…...

硬件原理图设计规范(二)

1、可编程逻辑器件 编号 级别 条目内容 备注 1 推荐 FPGA的LE资源利用率要保证在50%~80%之间,EPLD的MC资源的利用率要保证在50%~90%之间。对于FPGA中的锁相环、RAM、乘法器、DSP单元、CPU核等资源,经过精确预算,…...

复旦微ZYNQ7020全国产替代方案设计

现在国产化进度赶人,进口的芯片只做了个功能验证,马上就要换上国产的。国内现在已经做出来zynq的只有复旦微一家,已经在研制的有上海安路,还有成都华微(不排除深圳国威也在做,毕竟这个市场潜力很大&#xf…...

蓝桥杯真题——自动售水机

2012年第四届全国电子专业人才设计与技能大赛“自动售水机”设计任务书1. 系统框图接下来我们将任务分块: 1. 按键控制单元 设定按键 S7 为出水控制按键,当 S7 按下后,售水机持续出水(继电器接通,指示 灯 L10 点亮&…...

软件质量保证与测试 课程设计 测试报告 缺陷报告撰写方法

测 试 报 告 2020年 6月 1日 测试项目 程序员 测试人 测试阶段: □集成 √系统 □ 测试日志编号清单 1,2,3,4,5,6,7,8,9,10 遗留错误说明:(测试后仍然遗留下来未解决的错误及其说明) 1.系统界面不够友好&…...

vue2和vue3中路由的区别和写法?

前言:Vue 2 和 Vue 3 中路由的主要区别在于使用的路由库不同。在 Vue 2 中,通常使用 Vue Router 作为路由库;而在 Vue 3 中,Vue Router 仍然是官方推荐的路由库,但也可以选择使用新的路由库 - Vue Router Next。下面分…...

【数据结构】第四站:单链表力扣题(一)

目录 一、移除链表元素 二、链表的中间结点 三、链表中倒数第k个结点 四、反转链表 五、合并两个有序链表 六、分割链表 一、移除链表元素 题目描述:力扣 法一:直接循环依次判断 对于这个题目,我们最容易想到的一种思路就是&#xff0c…...

SAP BPC简介

BPC是SAP在financial application领域主推的产品,由于从原有产品线发展而来,产品本身有两个版本,分别是基于MS OLAP平台和Netweaver OLAP平台。 整个系统分为.net前台和abap后台。由于abap端的数据结构与.net数据结构的差异,所以没…...

Linux网络概述

写咋前面 今天,我们需要初步的认识一下Linux中网络的基本原理,只有大家对这个有一个初步的认识,后面我们学习起来才会更加的简单容易.计算机语言知识那么多,但是Linux不是.面试时,面试官总是会有问题难住你,我们后面需要看看书,这一点非常重要.我们现在谈的是脉络,.是框架.这些…...