1.让自己习惯C++

将构造函数声明为explicit,可阻止被用来执行隐式类型转换,仍可被用来进行显示类型转换

class C{
public:
    explicit C(int x);
}

Accustoming Yourself to C++ #

1.View C++ as a federation of languages #

  • C
  • Object-Oriented C++
  • Template C++
  • STL

2.Perfer consts,enums,and inlines to#defines #

一旦宏被定义,在其后的编译过程中一直有效,除非在某处被#undef

const double AspectRatio = 1.653;
const char* const authorName = "Scott Meyers";
const std::string authorName("Scott Meyers");

对于单纯常量,最好以const对象或者enums替换#defines

class GamePlayer{
private:
	static const int NumTurns = 5;//新一点的编译器才支持声明时定义
    int scores[NumTurns];
}
class GamePlayer{
private:
	enum{ NumTurns = 5};
    int scores[NumTurns];
}

对于形似函数的宏(macros),最好改用inline函数替换#defines

#define CALL_WITH_MAX(a, b) f((a) > (b) ? (a) : (b))    //不建议

//建议使用inline,宁可用编译器替换预处理器
template<typename T>
inline void callWithMax(const T& a,const T& b)
{
    f(a > b ? a : b);
}

3.Use const whenever possible #

char greeting[] = "Hello";
const char* p = greeting;//non-const pointer,const data
char* const p = greeting;//const pointer,non-const data
const char* const p = greeting;//const pointer,const data

迭代器中使用const

std::vector<int> vec;
const std::vector<int>::iterator iter = vec.begin();
*iter = 10;
++iter;//错误

std::vector<int>::const_iterator cIter = vec.begin();
*cIter = 10;//错误
++cIter;

4.Make sure that objects are initialized before they’re used #

  • 永远在使用对象之前 先将它初始化
  • 为内置对象进行手工初始化,因为C++不保证初始化它们
  • 确保每一个构造函数都将对象的每一个成员初始化
  • 总是使用成员初始列(member initialization list)
  • 当你在成员初始值列中条列各个成员时,最好总是以其声明次序为次序
ABEntry::ABEntry()
    :theName(),//调用theName的default构造函数
	theAddress(),
	the Phones(),
	numTimesConsulted()
{
}
  • 为免除“跨编译单元之初始化次序问题”,主以local static 对象替换non-local static 对象

所谓编译单元(translation unit)是指产出单一目标文件(single object file)的那些源码

non-local static 对象:global或位于namespace作用域内,抑或在class内或file 作用域内被声明为static的对象

如果某编译单元内的某个non-local static 对象的初始化动作使用了另一编译单元内的某个non-local static 对象,它所用到的这个对象可能尚未被 初始化,因为C++对“定义于不同编译单元内的non-local static 对象”的初始化次序并无明确定义