第一章:效率
Item M19:理解临时对象的来源
1.C++临时变量指的是匿名变量,匿名变量带来了构造和析构的开销
2.如果要返回一个对象,最好不要返回局部变量,它会带来两次的构造和一次的析构,可以通过调用构造函数构造一个匿名变量进行返回
Item M21:通过重载避免隐式类型转换
1.通过单参构造函数可以隐式的将其参数转换为该类的对象,此时会发生构造的开销,为避免这种隐式转换,可以为该操作定义至少包含一个该类以及需要的另外一个类型为参数的操作符
2.在 C++中有一条规则是每一个重载的 operator 必须带有一个用户定义类型 的参数
第二章:技巧
Item M25:将构造函数和非成员函数虚拟化
1.虚拟构造函数是指能够根据输入给它的数据的不同而建立不同类型的对象的函数。当你有一个指针或引用,但是不知道其指向对象的真是类型时,你可以调用虚拟函数来完成特定类型(type-specific)对象创建
2. 虚拟拷贝构造函数:返回一个指针,该指针指向一个调用该函数对象的新的拷贝。如果基类函数的返回类型是一个指向基类饿得指针(或引用),则子类的函数可以返回一个指向子类的指针(或引用)
3.构造函数不能真的称为虚函数——虚函数对应一个vtable,这个vtable存储在对象的内存空间。如果构造函数是虚的,就需要通过vtable来调用,可是对象还没有实例化,也就是内存空间还没有,无法找到vtable,所以构造函数不能是虚函数。
Item M26:限制某个类所能产生的对象数量
1.通过将类的构缺省造函数/单参构造函数和拷贝构造函数声明为private,防止外部显示的调用
2.不要将含有静态成员变量的函数声明为inline,因为内联会将函数展开,造成程序包含多个静态变量
3.单利模式的例子:
class PrintJob; // forward 声明 // 参见 Effective C++条款 34class Printer {public: friend Printer& thePrinter(); // 全局函数声明为printer类的友元,以合法访问private的构造函数,此处也可以使用静态函数实现相同的效果private: Printer(); // 私有构造函数 Printer(const Printer& rhs); // 私有构造函数 //...}; Printer& thePrinter() { static Printer p; // 单个打印机对象 return p; }// 第一,唯一的 Pritner 对象是位于函数里的静态成员而不是在类中的静态成员,这样做是非常重要的。在类中的静态对象实际上总是被构造(和释放),即使不使用该对象。 // 只有第一次执行函数时,才会建立函数中的静态对象,所以如果没有调用函数,就不会建立对象。 // 与一个函数的静态成员相比,把 Printer 声明为类中的静态成员还有一个缺点,它的初始化时间不确定
4.一个具有对象计数功能的基类
templateclass Counted {public: class TooManyObjects {}; // 用来抛出异常 static int objectCount() { return numObjects; }protected: Counted(); Counted(const Counted& rhs); ~Counted() { --numObjects; }private: static int numObjects; static const size_t maxObjects; void init(); // 避免构造函数的}; // 代码重复templateCounted::Counted() { init(); } templateCounted::Counted(const Counted&) { init(); } templatevoid Counted::init() { if (numObjects >= maxObjects) throw TooManyObjects(); ++numObjects; } class Printer : private Counted{public: // 伪构造函数 static Printer * makePrinter(); static Printer * makePrinter(const Printer& rhs); ~Printer(); void submitJob(const PrintJob& job); void reset(); void performSelfTest(); //... using Counted::objectCount; // 参见下面解释 using Counted::TooManyObjects; // 参见下面解释private: Printer(); Printer(const Printer& rhs); };