Effectice C++ 1 让自己习惯C++
让自己习惯C++
条款02:尽量以const,enum,inline替换define
单纯的常量,最好用const或enums替换#defines
形似函数的宏,用函数inline来替换#defines
条款03: 尽可能使用const
const出现在*左边,说明被指物是一个常量,出现在右边说明指针本身是一个常量,出现在两边说明都是常量。
std::vector<int> vec;
const std::vector<int>::iterator iter = vec.begin(); //等价于T* const
*iter = 10; //right
++iter; //error,不能改变指向的对象
std::vector<int>::const_iterator cIter = vec.begin(); //等价于const T*
*iter = 10; //error
++iter; //right
class TextBlock {
public:
const char& operator[](std::size_t position) const {
return text[position];
}
char& operator[](std::size_t position) {
return const_cast<char&>(static_cast<const TextBlock&>(*this)[position]);
}
private:
std::string text;
};
这段代码使用const operator[]实现了non-const的功能,主要进行了两次强制类型转换。首先将*this转换为const TextBlock&,以此可以调用const operator[],然后使用const_cast<char&>去掉const属性,转换为char&
使用non-const成员函数调用const成员函数可以,但是反过来绝对不行,并且non-const调用const可以避免代码重复。
条款04:确定对象被使用前已先被初始化
初始化的顺序:基类->派生类.按照初始化列表里的顺序初始化,尽量按照定义的顺序来写初始化列表的顺序。
函数内的static对象成为local static对象,其他的称为non-local static对象。
为了免除“跨编译单元初始化次序”问题,用local static对象替代non-local static对象。
//FileSystem.h
class FileSystem {
public:
std::size_t numDisks() const;
};
extern FileSystem tfs; //non local static
class Directory {
public:
Directory(params);
};
Directory::Directory(params) {
std::size_t disks = tfs.numDisks(); //使用tfs对象
}
Directory tempDir(params);
上述代码就会出现初始化次序的问题,当我们调用初始化tempDir的时候无法保证tfs被初始化,因为tfs属于其他文件的内容,不一定初始化了。
C++保证:函数内的local static对象会在“该函数被调用期间” “首次遇上该对象定义式”时被初始化。以“函数调用”替换“直接访问non-local static”对象,保证引用的对象已经初始化。
class FileSystem{...};
FileSystem& tfs() {
static FileSystem fs; //定义并初始化一个local static对象
return fs;
}
class Directory{...};
Directory::Directory(params) {
std::size_t disks = tfs().numDisks(); //使用tfs对象,此时执行tfs的初始化
}
Directory& tempDir() {
static Directory td;
return td;
}
浙公网安备 33010602011771号