条款5
对定制的类型转换函数保持警觉
在class中可定制两种类型转换函数,一个是单自变量的构造函数(如果带默认参数,可以有多个变量),二是operator 类操作符的重载,这里的内容较基础。对于单自变量构造函数,现在可以用explicit 关键字,要求显示构造,即可避免默认的转换行为,对于不支持explicit的编译器,作者提供了一种做法
class Array {
public:
class ArraySize {
public:
ArraySize(int s) : size(s) {}
int size;
}; // 代理类,代替array 构造函数的int
Array(ArraySize as) {...}
bool operator(const Array& ){...}
};
如上, Array的构造函数是单变量的, 且没有explicit。如果有以下代码
A ac[10];
int a = 12;
if (ac == a) {..}
感觉int a可以转为ArraySize, 然后转成Array,但是不行,编译器不会隐式调用两次用户自定以的转换函数。所以这里可以实现类似与explicit的功能。
条款6
区别自增自减操作符的前置 后置形式
这里就是后置自增的重载,有一个int参数。
且注意前置需要返回引用,后置返回const 值。
条款7
不要重载|| && 和逗号运算符
考虑如下代码
if(e1 && e2) {}
假设e1 e2是同一种class,且重载了&&,则表达式变为
if (e1.operator&&(e2))
// operator&& 是成员函数
if (operator&&(e1, e2))
// operator&& 是全局函数
这样丢失了&& 和 || 的短路求值特性,且全局函数重载时,无法知道e1 e2的求值顺序。
逗号表达式同理。
条款8
了解各种不同意义的new 和 delete
这里作者写的篇幅长,但其实没什么好说的,详细介绍,可以看看侯捷老师的内存管理课程。
简而言之,我们常用的new 是new operator 或者叫new expression, new expression内部 调用 operator new分配内存(operator new 内部可能直接调用malloc或者有一套自己的内存管理器),之后调用对象的构造函数。无法重载new expression, 但可以重载operator new, 且区分全局版本和成员函数版本。对于数组形式,其实差不多,只是会调用多次构造函数,delete 时会调用多次析构函数。
还有一种replacement new,这个是在已经分配好的内存上调用构造函数,这里作者给了一个共享内存的例子,在共享内存上调用replacment new.
replacemen new调用形式如下
pointer to obj = new (pointer to mem) ctor(param);
replacement new的写法比较特殊,让我想到了realloc,不过两者是不同的。
需要注意的是,new数组,记得delete数组,这里侯捷老师说,如果没有delete数组,new出来的空间会被释放,只是不会调用多次构造函数,这里说法不对请指正:)