从 2016 年 8 月份开始读这本书,限于目前大陆这边还没有中文版,所以是一边读一边翻译,但是自己的英语水平很一般,所以并没有以翻译的角度来写文章,怕自己的水平糟蹋了这本好书,所以基本上就是读懂了书中的意思,然后按照自己的理解写出来,截止 2017 年 6 月 5 号已经全部完成,目前是第一版,自己还在不断调整语句、格式和内容。力求不误导人。也希望广大的 C++爱好者可以给我提出一些修改建议。

Effective Modern C++ 目录

Item1 Understand template type deduction

Tips:

  1. 在模版类型推到的时候,如果传递的参数是引用类型,那么可以看作是非引用类型的,也就是说类型的引用部分被忽略。
  2. 当对通用引用类型的参数进行类型推导时,左值参数需要特殊对待。
  3. 当推导正常的参数类型时,const和volatile类型的参数会被忽略掉const和volatile部分。
  4. 在模版类型推导时,如果参数是数组或是函数名会退化为指针,除非这些参数是用来初始化 引用的。

Item2 Understand auto type deduction

Tips:

  1. auto类型推导通常和模版类型推导是一致的,但是auto类型推导对于{}会推导为std::initializer_list,但是模版类型无法对其进行推导
  2. auto对于函数返回值的类型推导和lambda参数类型推导时就是隐式的模版类型推导,并不是auto类型推导,对于{}无法进行推导

Item3 Understand decltype

Tips:

  1. decltype推导出来的类型几乎总是和目标类型是一致的
  2. 对于类型为T的左值表达式来说,decltype总是推导成T&
  3. C++14支持decltype(auto)声明变量和auto类似,可以对初始值进行类型推导,但是遵循的是decltype的规则

Item4 Know how to view deduced types

Tips:

  1. 类型推导可以借助于IDE,或者是编译器的错误输出以及Boost TypeIndex库
  2. 一些工具的类型推导结果可能是对我们所有帮助的,但是不一定是准确的,因此理解C++的类型推导规则仍然是必不可少的

Item5 Prefer auto to explicit type declarations

Tips

  1. auto变量必须初始化,可以缓解因为类型不匹配导致的可移植性或效率问题,可以缓解在重构过程中需要显示输入很长的变量类型名称。
  2. auto类型的变量受制于Item2和Item6中提到的陷阱

Item6 Use the explicitly typed initializer idiom when auto deduces undesied types

Tips

  1. 对于一些看不见的proxy类型,使用auto对这类初始化表达式进行类型推导会推导出错误的类型
  2. 通过显示的类型初始化惯用法可以强制auto推导出目标类型

Item7 Distinguish between () and {} when creating objects

Tips

  1. {}初始化是最广泛的初始化语法,它可以阻止窄化转换,并且避免了C++最复杂的语法解析
  2. 在构造函数做函数重载的时候,{}会优先匹配带有std::initializer_list参数的版本,即使其他构造函数看起来更匹配
  3. 对与std::vector两个参数的构造函数来说,其{}和()两种初始化方式有很大的不同
  4. 在模版中对于{}和()初始化如何进行选择是一个挑战

Item8 Prefer nullptr to 0 and NULL

Tips

  1. 优先使用nullptr替换0和NULL
  2. 避免同时重载带有整型参数和指针类型的参数

Item9 Prefer alias declarations to typedefs

Tips

  1. typedef 不支持模版化,但是using的别名声明可以
  2. 模版别名避免了传统的typedef带来的::type后缀,以及在类型引用的时候需要的typename前缀
  3. C++14给所有的C++11模版类型萃取提供了别名

Item10 Prefer scoped enums to unscoped enums

Tips

  1. C++98种的枚举众所周知是无作用域限制的
  2. C++11中的枚举类是有作用域限制的,不能进行隐式的类型转换需要使用C++的类型cast进行转换
  3. 无论是枚举类还是传统的枚举类型都支持指定底层的存储,对于枚举类来说默认的底层存储类型是int,而传统的枚举类型其底层存储是未知的,需要在编译器进行选择
  4. 枚举类总是可以进行前向声明的,而枚举类型则不行,必须是在明确指定其底层存储的时候才能进行前向声明

Item11 Prefer deleted functions to private undefined ones

Tips

  1. 优先使用delete来删除函数替换放在私有作用域中未定义的
  2. 任何函数都可以被删除,包括非成员函数,模版实例化等

Item12 Declare overriding function override

Tips

  1. 对于要重写的函数添加override关键字,让编译器负责检查
  2. 成员函数的引用标识符可以识别出(*this)的不同,是左值类型,还是右值类型

Item13 Prefer const_iterators to iterators

Tips

  1. 优先使用const_iterator替换iterator
  2. 为了是代码更通用,应该优先使用非成员函数版本的begin、end、cbegin、cend等

Item14 Declare functions noexcept if they won’t emit exception

Tips

  1. noexcept 是函数接口的一部分,这意味着调用者会依赖它
  2. 使用noexcept声明的函数相比于没有使用noexcept声明的函数代码更具可优化性
  3. noexpect对于move、swap、内存分配函数、析构函数等具有特别的价值
  4. 大多数函数都是异常中立的而不是noexcept

Item15 Use constexpr whenever possible

Tips

  1. constexpr对象是const,它的初始值是编译期的
  2. constexpr函数当传入的参数是编译期值时可以产生编译期的结果
  3. constexpr对象和函数可以广泛使用在非constexpr修饰的对象和函数上下文中
  4. constexpr关键字是对象以及函数接口的一部分

Item16 Make const member functions thread safe

Tips

  1. 为了让const成员函数是线程安全的,除非你确定不会在并发环境中调用
  2. 使用std::atomic变量可能会提供比mutex更好的性能,但是它仅仅适合操作单个变量和内存位置的操作

Item17 Understand special member function generation

Tips

  1. 编译器可能会生成的特殊成员函数会有默认构造函数、析构函数、拷贝操作、移动操作等
  2. 仅仅当类没有显式的声明移动操作、拷贝操作和析构函数的时候,编译器才会生成默认的移动构造函数
  3. 仅仅当类没有显式的声明拷贝构造函数、或是声明了移动构造函数时编译器才会生成默认的拷贝构造函数,和拷贝构造函数类似,仅仅当类没有显式的声明拷贝赋值操作符或是移动构造操作符时编译器才会生成默认的拷贝赋值操作符,不建议在具有明确声明的析构函数的类中生成复制操作。
  4. 成员函数模版不会阻止编译器生成特殊的成员函数

Item18 Use std::unique_ptr for exclusive-ownership resource management

Tips

  1. std::unique_ptr很小、很快、是一个只能移动的,独占管理资源的智能指针。
  2. 默认情况看下资源的删除使用的是delete,但是可以定制删除器,有状态的删除器会导致std::unique_ptr对象的大小增长。
  3. 将std::unique_ptr转换为std::shared_ptr是很容易的

Item19 Use std::shared_ptr for shared-ownership resource management

Tips

  1. std::shared_ptr提供了方便的方法进行垃圾回收可以对任意共享资源的生命周期进行管理。
  2. 相比于std::unique_ptr,std::shared_ptr对象通常情况下要大两倍,这是因为它要分配一个控制块,该控制块中包含了一个原子类型的引用计数、删除器、弱引用计数等
  3. 默认的资源释放是通过delete,但是std::shared_ptr支持自定义删除器,并且删除器的类型不影响std::share_ptr的类型和大小。
  4. 避免从一个指针类型的变量创建std::shared_ptr

Item20 Use std::weak_ptr for std::shared_ptr like pointers that can dangle

Tips

  1. std::weak_ptr可以探查std::shared_ptr指向的指针是否是悬挂指针
  2. 使用std::weak_ptr的一些潜在的场景包括,对象缓存、观察者模式、阻止std::shared_ptr的循环引用

Item21 Perfer std::make_unique and std::make_shared to direct use of new

Tips

  1. 相比于直接使用new,make系列的函数消除了源代码重复、提升了异常安全性,并且std::make_shared和std::allocate_shared生成的代码更小更快
  2. 对于希望自定义删除器以及通过{}进行初始值的设定时,不适合使用make系列函数
  3. 对于std::shared_ptr来说有两类场景不适合使用make系列函数,第一个就是需要自定义管理内存的,第二个就是管理大对象时,并且存在std::weak_ptr比std::shared_ptr生命周期更长的情况

Item22 When using the Pimpl, define specific member functions in the implementation file

Tips

  1. Pimpl的惯用法通过减少类的使用者对类实现的编译依赖从而缩小编译所花费的时间
  2. pImpl使用std::unique_ptr时,类的特殊函数声明放在头文件中,具体实现放在实现文件中的,避免了头文件中包含了std::unique_ptr析构相关的函数,导致编译错误
  3. 上面的建议适用于std::unique_ptr,但是不适用于std::shared_ptr

Item23 Understand std::move and std::forward

Tips

  1. std::move的实现其实是一个无条件将类型cast转换为右值类型,就本身而言没有移动任何东西
  2. std::forward就是根据参数的类型有条件的进行cast转换,如果输入的参数是一个右值就转换为右值,否则就转换为左值
  3. 无论是std::move还是std::forward在运行时都没有做任何事情

Item24 Distinguish universal references from rvalues reference

Tips

  1. 如果一个模版函数的参数类型是T&&,并且T的类型是推导出来的,或者一个对象使用auto&&这样的声明,那么这个函数的参数和要声明的对象都是通用引用类型
  2. 如果类型的声明不是type&&,或者没有发生类型推导,那么type&&表示的是一个右值引用
  3. 如果通用引用初始化的时候传入的是一个右值,那么就和右值引用一样,如果传入的是左值那么就喝左值引用是一样的

Item25 Use std::move on rvalue reference, std::forward on universal references

Tips

  1. 应用std::move到右值引用,std::forward到通用引用
  2. 对于右值引用和通用引用作为值从函数返回时本质上都是做了相同的事情
  3. 如果希望通过编译器进行返回值优化,则不要将std::move或std::forward应用到局部对象

Item26 Avoid overloading on universal references

Tips

  1. 在通用引用上进行重载,几乎总是会导致通用引用重载的版本比预期被调用的次数更频繁。
  2. 完美转发构造函数是非常有问题的,因为它们通常比非const左值的拷贝构造函数更好地匹配,并且可以劫持派生类对基类拷贝构造和移动构造函数的调用。

Item27 Familiarize yourself with alternatives to overloading on universal references
Item28 Understand reference collapsing
Item29 Assume that move operations are not present,not cheap,and not used
Item30 Familiarize yourself with perfect forwarding failure cases
Item31 Avoid default capture modes
Item32 Use Init capture to move objects into closures
Item33 Use decltype on auto&& parameters to std::forward them
Item34 Prefer lambdas to std::bind
Item35 Prefer task-based programming to thread- based
Item36 Specify std::launch::async if asynchronicity is essential
Item37 Make std::threads unjoinable on all paths
Item38 Be aware of varying thread handle destructor behavior
Item39 Consider void futures for one-shot event communication
Item40 Use std::atomic for concurrency, volatile for specific memory
Item41 Consider pass by value for copyable parameters that are cheap to move and always copied.
Item42 Consider emplacement instead of insertion

Effective Modern C++笔记汇总相关推荐

  1. [读书笔记]《Effective Modern C++》—— 移步现代 C++

    文章目录 前言 item7:区别使用 () 和 {} 创建对象 item8:优先考虑使用 nullptr 而不是 0 或者 NULL item9:优先考虑别名声明而非 typedefs item10: ...

  2. 《Effective Modern C++》笔记

    文章目录 绪论 第1章 型别推导 条款1:理解模板类型推导 情况1:ParamType 是个指针或引用,但不是万能引用 情况2:ParamType是万能引用 情况3:ParamType既非指针也非引用 ...

  3. 学习 慕课网 PHP工程师学习计划--我的笔记汇总

    为了进一步学习PHP,本周我选定了慕课网的PHP工程师学习计划, 从今天2015-07-06 10:24:47开始从头学习:计划本周尽快学习完成本课程,谨此作为笔记. 有个好的学习计划和思路非常非常重 ...

  4. 李永乐线性代数2020年强化课手写笔记汇总

    强化笔记整理如下,便于复习整理. [1]2020年李永乐线性代数强化笔记-行列式与矩阵 [2]2020年李永乐线性代数强化笔记-向量 [3]2020年李永乐线性代数强化笔记-线性方程组 [4]2020 ...

  5. 李永乐线性代数2020年基础课手写笔记汇总

    汇总于此,方便查询,如有帮助,副产品罢了. [1]线性代数手写笔记-行列式与矩阵 [2]线性代数手写笔记-向量 [3]线性代数手写笔记-线性方程组 [4]线性代数手写笔记-特征值和特征向量 [5]线性 ...

  6. biostar handbook: 第一周笔记汇总+第二周任务布置

    第一周笔记汇总 昨天和一位也在自学生信的同学交流自学的心境,他在我的唆使之下也在简书更新自己的笔记,可以搜索小郑的学习笔记.期间,他说道 非常庆幸自己能够坚持把自己学到的知识和困惑以文字的形式记录下来 ...

  7. python笔记视频_终于拿到!清华大佬Python视频+书+笔记汇总

    终于拿到!清华大佬Python视频+书+笔记汇总 清华学姐推荐的Python视频400集,拿走不谢!

  8. 笔记-软考高项-错题笔记汇总1

    错题笔记汇总1 1. 信息系统的规划工具 在制订计划时,可以利用PERT图和甘特图: 访谈时,可以应用各种调查表和调查提纲: 在确定各部门.各层管理人员的需求,梳理流程时,可以采用会谈和正式会议的方法 ...

  9. 机器学习及大数据经典算法笔记汇总

    机器学习及大数据经典算法笔记汇总 一.总结 二.机器学习及大数据算法 机器学习及大数据经典算法笔记汇总 一.总结 前面的博文,介绍了很多TensorFlow 以及 DeepLeaning 的算法.这里 ...

  10. 哈佛大学单细胞课程|笔记汇总(1-9)

    哈佛大学单细胞课程|笔记汇总 为什么做单细胞? 如何得到单细胞原始数据并转换成分析需要的矩阵格式 质控前的数据准备 质控 归一化和主成分分析 聚类分析与可视化 marker识别与注释 单细胞转录组测序 ...

最新文章

  1. java中单例实现常用的方式_Java单例的常见形式
  2. eBPF学习——抓取内核网络中的socket信息
  3. 空间刚架matlab_基本平面刚架MATLAB程序
  4. 移动端H5页面高清多屏适配方案
  5. ffmpeg命令行map参数的使用
  6. 中国燃油宝市场需求预测与投资前景趋势分析报告2022-2028年版
  7. 羽毛球双打“七宗罪”~很详细!
  8. CG CTF MISC Remove Boyfriend
  9. boost::fusion::as_vector用法的测试程序
  10. 数据可视化|实验一 绘图基础语法和常用参数
  11. JavaScript模式读书笔记 第3章 字面量和构造函数
  12. 2012递归求解单链表中的结点个数(C++,附递归函数思路讲解与手绘图)
  13. 简单易扩展的爬虫架构
  14. 2017安防市场新趋势:硬件免费 服务收费
  15. 《C++程序设计实践》实验1
  16. html5音乐播放器格式midi,HTML5 Audio时代的MIDI音乐文件播放
  17. java applet实例_java applet 一个简单的例子(applet+html)
  18. JS动态添加元素绑定点击事件,触发事件多次执行问题?
  19. uvm设计分析——reg
  20. 2010年度十大心理学发现

热门文章

  1. ifconfig eth0网卡配置
  2. HTML、css、js 特殊字符(空格符号)
  3. SpringBoot 生成带水印pdf | 中文字体问题
  4. linux tc 限速,linux tc 限速
  5. 带农历的html日历插件,魔镜日历插件-可生成带农历的日历月历年历-CDR插件
  6. 【原创】QT5-卸载精灵v1.0-卸载windows软件-简易版
  7. [AS3 狂想曲 K.07] BlazeDS 入门及配置 [FL 车在臣]
  8. GPT+UEFI双硬盘双系统安装
  9. java monitor
  10. 首届中国餐饮行业资本品牌创新发展(盐城)论坛圆满举办成功