Effective C++学习笔记
按孙中山先生的说法,这个世界依聪明才智的先天高下的三种人:先知先觉得发明家,后知后觉的宣传家,不知不觉的实践家。三者之中发明家最少最稀珍。
声明,定义,初始化的区别:
当你看到赋值符号时请小心,因为“=”语法也可用来调用copy构造函数:
Widget w3=w2;
幸运的是copy构造很容易和copy赋值有所区别。如果一个新对象被定义(例如以上语句中的w3),一定会有个构造函数被调用,不可能调用赋值操作。如果没有新对象被定义,例如 w1 = w2,就不会有构造函数被调用,那么当然就是赋值操作被调用。
1, Accustoming Yourself to C++
条款01:视C++为一个语言联邦 View C++ as a federation of languages
C++并不是一个带有一组守则的一体语言;它是从四个次语言组成的联邦政府,每个次语言都有自己的规约:
n C.说到底C++是以C为基础的。区块、语句、预处理、内置数据类型、数组、指针等统统来自C;
n Object_OrientedC++.class,封装,继承,多态、virtual函数(动态绑定)….等等;
n Template C++。这是C++的泛型编程部分,也是大多数程序员经验最少的部分。你不必为每一种特定类型都创建一个对象或一个防范;
n STL。STL是个template程序库,容器、迭代器、算法等。
请记住:
C++高效编程守则视状况而变化,取决于你使用C++的哪一部分。
条款02:尽量以const,enum,inline替换#define。 Preferconsts,enums,and inlines to defines.
这个条款或许可以改为“宁可以编译器替换预处理器”比较好,因为或许#define不被视为语言的一部分。
我们常以常量替换#defines,有两种特殊情况:
1,定义常量指针。
const char* const authrname=”Scott Meyers”;
2, class专属常量,为了确保此常量至多只有一份时候实体,你必须让它成为一个static成员:
必须在实现文件中提供定义;
还可以用enum:
enum的行为较像#define而不想const,枚举是不占用空间的,编译器在预处理时会把具体的枚举值直接填入程序中,可以在VC的汇编窗口查看, 其实枚举等于是定义为值的宏而已
另一个常见的#define误用情况是以它实现宏。宏看起来像函数,但不会招致函数调用带来的额外开销,常用inline来代替
请记住:
对于单纯常量,最好以const对象或enums替换#defines。
对于形似函数的宏,最好用Inline函数替换#defines。
条款03:尽可能使用const。Use constwhenever possible.
如果关键字const出现在星号左边,表示被指物是常量;如果出现在星号右边,表示指针自身是常量;如果出现在星号两边,变速被指物和指针两者都是常量。
Stl迭代器:
前者表示这个迭代器不得指向不用的东西,但它所指的东西的值时可以改动的。如果你希望迭代器所指的东西部可被改动,你需要用const_iterator;
请记住;
n 将某些东西声明为const可帮助编译器侦测出错误用法;
n 编译器降至实施bitwise constness;const成员函数不可以更改对象内任何non-static成员变量;
n 当const和non-const成员函数有着实质等级的实现时,令non-const版本调用onst版本可避免代码重复;
条款04:确定对象被使用前已先被初始化。
确保每一个构造函数都将对象的每一个成员初始化,初始化和赋值不同,c++规定,对象的成员变量的初始化动作发生在进入构造函数本体之前。
这个构造函数和上一个的最终结果相同,但通常效率较高。基于赋值的那个版本首先调用默认构造函数为三个变量设初值,然后立刻再对它们赋予新值。
如果成员变量是const或references,它们就一定需要初值列表,不能被赋值,所以总是使用成员初值列。
C++有着十分固定的“成员初始化次序”。次序总是相同:base classes更早于其derived classes被初始化,而class的成员变量总是以其声明次序被初始化。
n 请记住:
n 为内置型对象进行手工初始化,因为C++不保证初始化它们。
n 构造函数最好使用成员初值列,而不要在构造函数本体内使用赋值操作。初值列列出的成员变量,其排列次序应该和它们在class中的声明次序相同。
n 为免除“跨编译单元之初始化次序”问题,请以localstatic对象替换non-localstatic对象。