Effective C++读书笔记(四)

条款18: 让接口容易被正确使用,不易被误用

  • “促进正确使用”的办法包括接口的一致性,以及与内置类型的行为兼容
    • 获得大小时全部用size而不是偶尔有length
    • 如果和int类似,就要是他的行为(比如加减)和int一样
  • “组织误用”的办法包括建立新类型,限制类型上的操作,舒服对象值,以及消除客户的资源管理责任
  • shared_ptr支持定制型删除器,消除了”cross-DLL problem”,可用来接触互斥锁
    • cross-DLL problem: 对象在DLL中被new创建,却在另一个DLL中内delete销毁

条款19: 设计class犹如设计type

设计class需要面对的问题:

  • 新type的对象应该如何被创建和销毁?
    • 构造函数和析构函数
  • 对象的初始化和对象的赋值该有什么样的差别?
  • 新对象如果被passed by value(按值传递),意味着什么?
    • copy构造函数
  • 什么是新type的”合法值”?
  • 新type需要遵循某种继承关系吗?
  • 新type需要什么样的转换?
  • 什么样的操作符和函数对新type是合理的?
  • 什么样的标准函数应该驳回(private)?
  • 与type有关系的其他class或type?
  • 什么是新type的”未声明接口”?
  • 新type有多一般化?(是否应该直接定义template)
  • 真的需要定义这样的一个type吗?

条款20: 宁以pass-by-reference-to-const替换pass-by-value

  • 尽量以pass-by-reference-to-const替换pass-by-value。前者通常比较高效,并可避免
    • 切割问题: 若传入对象是子类但传入类型是父类类型,由于调用的copy构造函数是父类的,会导致在函数内对象只含有对象的父类部分
  • 具体情况具体分析,有些时候(例如STL)使用pass-by-value比较合适

条款21: 必须返回对象时,不要返回其reference

  • 不要返回指针或者引用指向local stack对象或者heap-allocated对象,或返回指针或者引用指向一个local static对象而有可能同时需要多个这样的对象。
    • local stack: local stack对象在函数退出之前会被销毁
    • heap-allocated: 无法反之内存泄露,无法每次都delete
    • local static对象: 多个对象的local static对象引用都指向同一个

条款22: 将成员变量声明为private

  • 尽可能的把成员变量声明为private
    • 赋予客户访问数据的一致性
    • 细微划分访问控制
    • 实现封装
  • protected并不比public更具封装性

条款23: 宁以non-member、non-friend、替换member函数

  • 提高封装性:不增加能够访问class内之private成分的函数数量
  • 提高包裹弹性(packaging flexibility): 可以使该non-member函数位于一个namespace内(namespace可跨越多个源码文件),符合C++标准程序库的组织方式
  • 机能扩展性: 由于此类便利函数放在多个头文件但属于同一namespace,客户可以扩展这一组函数

条款24: 若所有参数皆需类型转换,应为此采用non-member函数

例子:class有理数和int类型数相乘,即使定义了member operator函数,却不能满足交换律。使用non-member函数或许是个更好的选择

条款25: 考虑写出一个不抛异常的swap函数

(以后补充)