effective_cpp读书笔记
序
声明, 签名(参数, 返回类型), 定义(内存的地点)
构造函数 explicit 禁止隐式类型转换
copy 构造函数: 对象如何以值传递
少用 define
旧式编译器也许不支持上述语法,它们不允许 static 成员在其声明式上获得初值。此外所谓的 “in-class 初值设定”也只允许对整数常量进行。如果你的编译器不支持上述语法,你可以将初值放在定义式:
class CostEstimate { |
the enum hack
class C{ |
用 inline 函数代替 define
template<typename T> |
尽可能使用 const
编译器强制实行约束
迭代器的 const 和指针一样
const_iterator 等价于 const T*
const iterator 等价于 T* const
class C{ |
¥# const 成员函数
在函数声明最后加 const const int add(int a)const{}
可以重载
不会对这个类的对象的数据成员作出任何改变, 即在 const 成员函数中无法赋值
对象可否调用函数 | const 对象 | noconst 对象 |
---|---|---|
const 成员函数 | yes | yes |
noconst 成员函数 | no | yes |
const 成员函数也不要提供修改途径(比如返回引用), 虽然可以通过编译
可以通过声明成员变量为 mutable
在 const 函数中改变对象的数据
对象使用前初始化
对于内置类型进行手动初始化, 对于其他类型确保构造函数对每一个成员都进行初始化
赋值!=初始化
对象成员变量的初始化发生在进入构造函数本体之前(使用初始化列表)
\1) If the constructor is for the most-derived class, virtual bases are initialized in the order in which they appear in depth-first left-to-right traversal of the base class declarations (left-to-right refers to the appearance in base-specifier lists)
\2) Then, direct bases are initialized in left-to-right order as they appear in this class's base-specifier list
\3) Then, non-static data member are initialized in order of declaration in the class definition.
\4) Finally, the body of the constructor is executed
class C{ |
ABEntry::ABEntry(int a):A(a), Father(a), otherFunc(){ |
non-local static 对象初始化: 由于 c++ 未规定这类变量的初始化顺序, 如果别的编译单元使用该对象, 可能得到未初始化的对象
因此, 需要将 non-local static 对象放到专属函数中, 使其变成 local-static 对象, 函数返回 reference
ClassC& c(){ |
默认函数
空类: 拷贝构造该函数, 拷贝操作符, 析构函数, 如果没有任何构造函数: 默认构造函数
默认拷贝: 将来源对象的每一个 non-static 成员变量拷贝到目标对象。
class C{ |
virtual 析构函数
析构函数的运作方式是, 最深层派生(most derived)的那个 class 其虚构函数最先被调用, 然后是调用其每一个 base class 的析构函数
构造函数析构函数不应该调用 virtual 函数
构造函数中调用虚函数, 在基类构造函数执行时会调用基类的虚函数而不会下降到派生类
析构函数调用虚函数, 派生对象的成员变量呈现未定义状态, 编译器会无视他们, 进入基类析构函数后对象就成了一个基类对象
operator= 返回 *this 引用, 处理自我赋值
实现连锁赋值
自我赋值:
C& C::operator=(const C& rhs){ |
将resource放到对象中
auto_ptr
对象在进入构造函数体时就已经完成初始化?
小心返回 reference
¥