Effectice C++ 1 让自己习惯C++

让自己习惯C++

条款02:尽量以const,enum,inline替换define

单纯的常量,最好用constenums替换#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;
}

posted on 2022-03-09 21:08  翔鸽  阅读(28)  评论(0编辑  收藏  举报