《Effective C++》阅读总结(四): 设计、声明与实现
第四章: 设计与声明
18. 让接口更容易被正确使用,不易被误用
- 将你的class的public接口设计的符合class所扮演的角色,必要时不仅对传参类型限制,还对传参的值域进一步限制。
19. 设计class犹如设计type
- 内置类型如int、float等,本质也是一个class,用户自定义的class的行为和状态应当与内置类型类似的。设计class时,首先要考虑构造和析构、然后是赋值操作如何实现、考虑class是否要继承某一已有class、尽量使你的class一般化等等需要考虑的问题。
20. 宁以pass-by-reference-to-const替代pass-by-value
- 这个准则很常见,使用const引用传参以避免拷贝和修改入参。看具体场景,如果是需要修改入参,那么就不要加const、如果入参是简单内置类型,拷贝不怎么消耗资源,那么直接传值也是可以的。同样,使用指针也是一样的道理。此外,传class的引用或指针也可以避免对象切个问题,例如函数接受一个父类对象,当传入子类对象时,父类对象构造函数会被调用,此时子类的属性就会丢失,即切割问题,这是不希望的。
21. 必须返回对象时,不要妄想返回reference
- 很显然的一点就是,你不能返回一个locakl对象的指针或者引用,因为,函数调用结束后,所有存储在栈上的local对象都将被销毁。此外,可以返回在函数内构造的堆对象的指针,但尽量不要返回其引用,引用如果在返回后没有保护好而被覆盖,则造成内存泄漏。
22. 将成员变量声明为private
- 这是一个封装合理的class应当遵守的规则,成员变量声明为private的话,可以通过public接口间接控制成员变量,并加以特殊限制。这样做也有缺点,就是编写代码无法直接修改成员变量,代码量增加。如果只需要保存读取数据,不做其他操作,那么声明一个结构体是一个不错的选择。
我们一把不使用protected成员,没什么用。
23. 宁以non-member、non-friend替换member函数
- 如果一个操作是一般性的,并不是class特有的,那么将其抽离class单独声明定义。
24. 若所有参数都需要类型转换,请为此采用non-member函数
- 这里的所有参数包括this指针,所以连this指针都需要转换类型,那么这个函数其实就不应该是这个class的成员函数,应当抽离class。
25. 考虑写一个不抛出异常的swap函数
- 使用
std::swap吧,我觉得目前够用了
第五章 实现
我们写c++代码,一个是如何设计架构,即定义class及其成员函数和成员数据,以及不同class之间的通讯关系;另一个是如何具体实现每个函数,对每个函数或成员函数的功能进行实现,这部分每个功能相对独立,比较底层,但其中也有些需要注意的点,主要有以下几个:
26. 尽可能延后变量定义式的出现时间
- 这样可以提高程序的效率,但我并不认为会提高程序的可读性。对于那些不是非常在意运行效率的函数,可读可维护性要排在效率前面,如初始化,而那些会循环调用很多次的代码,如模型推理计算,效率至上。此外,编译器也会尽可能优化代码,以提高运行时效率。
27. 尽量少做转型动作
C++中的cast方法有四种:
①const_cast:用于移除对象身上的const属性,只此一个功能。常用。低风险。
②static_cast:用于强制隐式转换。例如将int转为double,将基类指针转为子类指针时不进行安全检查。不可用于移除const属性。常用。低风险。
③dynamic_cast:用于执行类继承体系中安全向下转型。也就是用来决定某个对象是否归属类继承体系中的某个类型。比如可以将多态基类(包含虚函数的基类)的指针强制转换为派生类的指针,很耗时,不常用。高风险。
④reinterpret_cast:用于执行低级转型,例如将int*转为int,执行的是逐个比特复制的操作。 不用。高风险。
- 所以,首先尽量避免转型,或者对于不可避免的转型,将转型操作隐藏到函数里面,并且尽量使用C++style的转型方法,不要使用早期C风格的那种方法。在类继承体系中进行上行转换时,
dynamic_cast和static_cast效果一样且安全,但下行转换时,dynamic_cast会进行类型安全检查且耗时,而static_cast不进行检查。所以如果有必要且明确基类指针是哪个子类时,通常使用static_cast即可。
移除const属性是危险的,如无十分必要请不要这样做,肯定有其他方法规避这种危险操作。
28. 避免返回handle指向对象的内部成分
- 即不要返回指向对象数据成员的指针或引用,以保证对象的封装性,防止外部改变对象内部数据。如果非要这样做,请将返回值加上const属性,以禁止修改。
29. 为异常安全所做的努力是值得的
- 这条准则不好总结,大概来说就是对那些可能导致异常发生的函数进行异常捕获并进行适当的处理,以避免内存泄漏。
30. 透彻了解inline的里里外外
- 直接定义在class体内的成员函数默认是内联的,也可以在class体外显式声明内联函数,但最终是否执行内联替换由编译器决定,它只会将那些小型、频繁调用的函数编译为内联函数,这样能尽可能降低代码膨胀并提升程序执行速度。
31. 将文件间的编译依存关系降至最低
- 即让代码依赖声明式而非定义式,这样定义式发生改变不会导致依赖于该定义式的其他代码也需要重新编译。基于此构想的两种方案是:
Handle class和interface class。这是在我们平时构建工程的时候经常遇到的两种设计方法。 - 程序库头文件应该以“完全且仅有声明式”的形式存在。其他代码依赖此文件即可。
小结:
以上即总结。明天上班。
《Effective C++》阅读总结(四): 设计、声明与实现的更多相关文章
- Redis源码阅读(四)集群-请求分配
Redis源码阅读(四)集群-请求分配 集群搭建好之后,用户发送的命令请求可以被分配到不同的节点去处理.那Redis对命令请求分配的依据是什么?如果节点数量有变动,命令又是如何重新分配的,重分配的过程 ...
- 【原】AFNetworking源码阅读(四)
[原]AFNetworking源码阅读(四) 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 上一篇还遗留了很多问题,包括AFURLSessionManagerTaskDe ...
- 【原】SDWebImage源码阅读(四)
[原]SDWebImage源码阅读(四) 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 SDWebImage中主要实现了NSURLConnectionDataDelega ...
- GroupBy(..)的四种声明方式的理解及调用
这里我们以 List<Student> studs作为 source,但是注意,studs中的学生可以是分别属于不同的班级和年级 先看GroupBy的第一种声明: public stati ...
- js的数据类型、函数、流程控制及变量的四种声明方式
运算符 基本运算符 加 + 减 - 乘 * 除 / 取余 % 自增 ++ eg: 1++ 或 ++1 自减 -- eg: 1-- 或 --1 注:++或--写在前面表示优先级最高,先进行自增或者自减 ...
- Effective C++笔记04:设计与声明
条款18:让接口easy被正确使用,不易被误用 1,好的接口非常easy被正确使用,不easy被误用.你应该在你的全部接口中努力达成这些性质. 2,"促进正使用"的办法包含接口的一 ...
- EC++学习笔记(四) 设计与声明
条款18:让接口容易被正确使用,不易被误用 必须考虑客户可能做出什么样的错误(防御式编程)std:shared_ptr会自动使用它的"每个指针专属的删除器",消除了"cr ...
- 从SpringBoot启动,阅读源码设计
目录 一.背景说明 二.SpringBoot工程 三.应用上下文 四.资源加载 五.应用环境 六.Bean对象 七.Tomcat服务 八.事件模型 九.配置加载 十.数据库集成 十一.参考源码 服务启 ...
- Effective Java 阅读笔记——方法
38:检查参数的有效性 每当编写方法或者构造器的时候,应该考虑它的参数有哪些限制,在方法的开头处对参数进行检查,并且把这些限制写入文档. 注意: 对于公有方法,应该使用@throws标签在文档中说明违 ...
- 《The Google File System》论文阅读笔记——GFS设计原理
一.设计预期 设计预期往往针对系统的应用场景,是系统在不同选择间做balance的重要依据,对于理解GFS在系统设计时为何做出现有的决策至关重要.所以我们应重点关注: 失效是常态 主要针对大文件 读操 ...
随机推荐
- Android.mk文件如何打日志信息
1. 在mk文件中添加:$(warning "xxx="$(变量名)) 2. 执行lunch,选一个分支,此过程中可以打出添加的log.
- JavaScript实现动态表格
运行效果: 源代码: 1 <!DOCTYPE html> 2 <html lang="zh"> 3 <head> 4 <meta char ...
- python 简要小结
初学python 简单总结部分内置函数 将两个数组合并为元组:zip() 解压:zip(*zip) range(a,b,c) 取值范围 起始:a 结尾:b 间隔:c (参数不能为空否则 ...
- css过渡效果和盒子缩放大小的结合
给盒子一个鼠标经过时放大里面的图片效果在css中使用过渡效果transition结合 <html lang="en"> <head> <meta ch ...
- SpringMVC 解析(四)编程式路由
多数情况下,我们在使用Spring的Controller时,会使用@RequestMapping的形式把请求按照URL路由到指定方法上.Spring还提供了一种编程的方式去实现请求和路由方法之间的路由 ...
- Java-GUI编程之绘图
绘图 很多程序如各种小游戏都需要在窗口中绘制各种图形,除此之外,即使在开发JavaEE项目时,有时候也必须"动态"地向客户 端生成各种图形.图表,比如 图形验证码.统计图等,这都需 ...
- springdata jpa多表查询的方式
方式一:使用@Query注解方式查询主要有JPQL方式,也就是面向对象的方式,这种情况下查表其实查的是对象,字段是实体中的属性,该方式可以直接映射到实体,如下图. 使用jpql的方式模糊查询时候不能使 ...
- mongodb replication
官方文档:https://docs.mongodb.com/manual/replication/ 启动参数: 通过linux的包管理器(例如:yum)安装的mongodb会产生一个默认的配置文件:/ ...
- 1.Docker容器学习之新生入门必备基础知识
0x00 Docker 快速入门 1.基础介绍 描述:Docker [ˈdɑ:kə(r)] 是一个基于Go语言开发实现的遵循Apache 2.0协议开源项目,目标是实现轻量级的操作系统虚拟化解决方案: ...
- 新手小白入门C语言第二章:基本语法
1. 语句 C 语言的代码由一行行语句(statement)组成.语句就是程序执行的一个操作命令.C 语言规定,语句必须使用分号结尾,除非有明确规定可以不写分号. 如: int x = 1; 这就是一 ...