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;
}