笔记,两本书的记录,不值得看。以前记在印象笔记的,搬迁出来做个记录

GENETIC

item 1 iterator 有效性,不能解引用无效的迭代器。未定义行为。

item 2~3 实现case-insensitive 字符串 理解base_string原理

item 4~5 具有最大可复用性的通用容器

item 6 临时对象

item 7 标准库


EXCEPTION-SAFETY

item 8~17 异常安全 stack pop 为什么设计成void

item 18 代码复杂性 如果允许异常,代码隐藏多少路径

item 19 代码复杂性2 异常安全,基本保证,不泄露,强力保证,commit-or-rollback

  • 要strong-guarantee 可能就需要牺牲点性能(校验代码保证异常安全,包括拷贝构造异常,RAII,rollback等)如果函数具有多重side-effect那就得封装分层来解决

类设计与继承

item 20~25 class mechanics class技术

  • 传引用,explicit关键字等小建议
  • 几个小建议,虚基类 using override默认值不要乱改
  • 几个OO概念,确定is-a/has-a关系,不要乱用public继承,
  • 设计模式,pimpl惯用法,函数方法和继承-复写方法比较
  • 重申上面的观点,不要滥用继承

PIMPL

item 26~28 编程依赖

item 29 编程级防火墙 (compilation firewalls)

item 30 fast pimpl


名称搜索,命名空间,接口原则

item 31 名称搜索 ADL

item 32~34 接口原则


内存管理

item 35——37 内存管理

  • 内存基本概念
  • RAII

traps. pitfalls. and anti-idioms

item 38 对象等同?资源可能泄露

item 39 自动转换

item 40 对象的生命周期

item 41 对象的生命周期2

  • 以上两条主要讲成员函数placement-new在this上不可取,不安全。比如继承引入的切割问题,也导致开销大,非异常安全,改变了对象的生命周期

杂项 miscellaneous

item 42 变量初始化 T t();会被解析成函数声明

item 43 const

item 44 casts

item 45 bool,bool语义

item 46 forwarding functions 函数调用转发效率问题 传引用,除非profiler避免内联

item 47 control flow中的异常安全


泛型程序设计与c++标准库

item1 流 理解cin/cout 实现一个echo 理解工程设计原则-即尽可能的提高扩充-尽量提高封装

item2 理解std::remove 原理() 由find(_if)实现,**++i != last;** 以及 erase-remove惯用法

item3 状态谓词带来的问题 stateful-predicate 没有好的解决方案,用上智能指针,共享谓词状态。还是考虑需求为啥要这样实现吧。

item4 扩充模板 用 traits 还是继承

  • 继承,约束接口,约束类(imperfect c++也讲过,就是函数指针赋值,让编译器帮你检查)
  • SFINAE 来匹配接口指针
  • 工厂类?将约束构造放在类内部,客户端类作为模板参数,来(内部特化)匹配出相应的构造
  • traits 高扩展,(如果嫌逐个类写traits麻烦也可以参考AA 的书中的解决办法)
  • 为了处理模板中的分类而是用继承不足以成为使用继承 的理由。

item5 typename 以及如何使用

  • 名字查找,模板实例化才知道,所以不能找到的符号会报错,所以需要typename暗示出来。
  • typedef hell

item6 容器,指针,和不是容器的容器

  • 原生指针和解引用迭代器有时候很有用,但是好考虑是否有效
  • fuck vector //bitvector,用vector vector deque

item7 使用vector和deque

  • 顺序容器优于数组,默认用vector ,经常在头尾插入删除就用deque
  • deque分页组织,在体积增长上优于vector,vector push_back要用reverse惯用法,否则低效(反复扩大->挪动)另外,reserve不会缩小空间(shrink_to_fit in c++11)可以用swap trick(shrink_to_fit应该也是这样实现的)
  • swap惯用法 包括上面的场景与clear操作(swap 一个空对象更trick一些,这点在effective stl 中也有提到,不过c++11应该优化了clear)

item8 set 与map

  • 关联容器,作为key相对位置不能变,key不能被强行改,否则内部的数据结构遍历就会失去控制(map就是const key)
  • set可以看成 map<Key,void>
  • 你必须知道你在做什么(如果你用const_cast强行改的话)

item9 f(a++) f(a);a++ 代码中的微小差别会带来影响吗

  • 多种语义 ,a 是类,那么a的operator++(int)实现是怎样的,f可能是宏,也可能是函数传引用参数或指针
  • 接着上面,第二种写法,考虑a 是迭代器,f是erase,迭代器失效就不能调用operator++(int)了,但第一种写法却是对的
  • 总而言之,两种写法都要小心,你必须知道你在做什么

item10 模板特殊化与重载

  • 显式特化 偏特化(只有类模板可以)
  • 函数模板特化,函数重载引入的歧义性

item11 熟悉泛型设计的例子

优化与性能

item12 inline

  • 你到底想优化什么,内联如果不是热点,反而适得其反使得提及增大cache 加大反而降低速度
  • profiler 说了算,优化原则,别用

item13~item16 缓冲优化 string实现 以及COW写时复制

  • 最佳缓冲区增长策略 logn
  • COW 一个应用,Linuxfork,引用计数,所谓的浅拷贝和深拷贝不过是返回this 还是new(this)
  • COW带来的问题,operator[](不能共享就new一个)(禁止拷贝也行),迭代器,线程不安全(这个和shared_ptr不是线程安全一个道理)(加锁性能损失也很大)
  • 新版std::sring 转而采用SSO,需要理解原理

异常安全

item17-19 构造函数失败 ->处理异常 ->未捕获异常

  • 对象生命期,如果构造函数异常了会怎样(初始化列表也可以加上try-block(就是有点难看)(就是function-try-block),且必须抛异常,所以尽量放在函数内部局部的处理(普通try-block))
  • 接上,只要任何一个基类或成员子对象构造失败,整体就构造失败,改变设计转向pimpl,而不是继承->还是耦合与内聚的问题
  • try-block 也不建议用在析构中,析构抛异常是傻逼行为(c++11 编译器会警告,noexcept)
  • 注意构造函数的异常规范,能用RAII就用RAII吧。
  • 接上,假设傻逼了,析构抛异常不处理,用if-std::uncaught_exception分支处理,会使语义复杂,也很傻逼。还不如用个try-clean_func-catch来处理。

item20-21 管理指针 ->auto_ptr?

  • 参数求值完成在函数调用前,考虑函数调用中的异常安全问题,比如new多个参数?参数可能构造失败
  • 试图使用auto_ptr解决问题,直接把参数改成auto_ptr 也是不行的,但有个临时方案,再封装一层函数模板返回auto_ptr临时对象,临时对象的生命周期只有一行,如果失败前面的参数资源也不会泄露
  • 或者就不要这么写,资源由智能指针托管就行了,别再入参里new

item22 异常安全与类的设计->如何写个operator=()

  • 假设类中有类成员(多个),考虑 class& operator=(class&)如何才能更安全 (万金油 pimpl)
  • 保证swap 异常安全,用swap( 上智能指针)

item23 异常安全与类的设计->继承带来的影响

  • 尽量不用继承来描述is-implemented-in-terms-of,考虑继承下的对象怎么实现operator=() (过于耦合)

继承与多态

item24-28 为什么要使用多继承 ->模拟多继承 ->纯虚函数 ->受控的多态

  • 为什么要使用多继承,不是接口抽象类就不要瞎继承了
  • 模拟多继承,->组合,像多继承那样安排就好了。
  • 切割问题,引入中间类避免
  • 纯虚函数,纯虚函数也可以提供默认行为,由派生类显式调用更明显些。
  • 接上,默认行为 + 装饰器模式,提供部分行为
  • 控制多态 ->友元函数。

内存及资源管理

item29-31 auto_ptr带来的问题 c++11 开始auto_ptr被废弃

  • auto_ptr 不能托管数组 数组new 比较坑爹 改进方案 抄一个auto_array, 写个adapter封装数组,不要用数组
  • auto_ptr拷贝构造的问题,delete两次(c++11 用unique_ptr取代,禁止拷贝)
  • 实现一个value_ptr(有点像加强版unique_ptr)

自由函数与宏

item32 递归声明

  • 函数指针如何返回自身? ->代理类封一层函数指针,绕出来,而不是void *硬刚,无开销,就是不能模板通用

item33 模拟嵌套函数

  • 嵌套类和局部类。实现operator()()(c++11 有lambda)

item34-35 宏带来的问题

  • 安全性问题 const替换
  • head-file guard 这个无法取代
  • 括号
  • 本质是名字替换。所以可能造成冲突,宏机制各个编译器实现有差别

杂项 MISC

item36 初始化 了解构造初始化拷贝初始化语义 (《深入了解c++对象模型》)

item37 前置声明消除编译期依赖 以及,不要把typedef当成类了,class string这种

item38 typedef

  • 偷懒 (所以说在c中,不值得用typedef来简写struct)
  • traits

item39-40 namespace

  • 不要在头文件中使用using 污染名字空间
  • using与声明顺序,不要放在#include前

书后是一个多线程 cow string实现(加锁),以及性能测试