main函数的返回值必须是int型。
在写C++程序时,大部分出现空格的地方可用换行符答题,但字符串字面量中的空格例外。另一个例外是空格不允许出现在预处理器指示中。
任何允许有制表符、空格或换行的地方都允许放注释对。
基本类型:bool, char, wchar_t, short, int, logn, float, double, long double.
整型字面量默认类型为int 或 long。可在后加L、l或U、u以及UL指定其类型。
浮点字面量默认为double,可在后加上F或L。
可在字符字面量后加L使之成为wchar_t。
连接字符串字面量和宽字符串字面量,其行为是未定义的。
C++ 保留了一些词用作操作符替代用于支持某些不支持C++ 操作符的字符集,这些词不能用作标志符,如:and or nor xor……
C++还保留了一组标志符用于标准库,标志符不能包含两个连续的下划线,也不能以下划线开头后跟一个大写字符。
C++支持两种初始化:复制初始化和直接初始化:
int ival(1024); //direct-initialization
int ival = 1024; //copy-initialization
非const 引用只能绑定到同类型的对象;const 引用则可绑定到相关但不同类型的对象或绑定到右值。
在头文件中,请不要用using 引入命名空间,要用完全限定的标准库名称。
当string 对象和字符串字面值混合连接时,+ 操作符左右必须至少有一个string 对象。
现代C++程序员倾向于使用迭代器而不是下标。所有的标准库容器都定义了相应的迭代器,只有少数几种才定义了下标操作。
非const 变量和运行时才知道其值的 const 变量不能用做数组的维数。
允许0字面量或编译时获得0值的const变量赋给指针,但不允许将一个值为0的 int 型变量赋给指针。
void 指针只支持几种有限的操作:与另一个指针比较;向函数传递void*指针或返回void* 指针;给另一个void*指针赋值。不允许使用void* 指针操纵它所指向的对象。
指针和引用的差别:引用必须在定义时初始化;引用总是指向同一个对象。
两个指针的减法操作的结果是ptrdiff_t 类型的。
typedef string *pstring;
const pstring cstr;
cstr是一个指向string 对象的 const指针!
动态分配数组时,如果数组元素具有类类型,将使用该类的默认构造函数实现初始化;如果数组元素是基本类型,则无初始化,但可在后加()强制初始化。
char *cp = new char[0]; //ok,but can't be dereferenced
但是此指针可以进行比较运算,+0,-0。
不要在一个表达式中对同一个变量进行多次++ 或 – 操作。
只能在最后一个case 或 default 中定义变量,这是为了避免出现代码跳过变量定义和初始化的情况。
goto 语句不能向后跳过变量定义语句。
标准异常类型只定义了一个what 函数,返回一个C字符串。
函数不能返回另一个函数或数组,但可以返回指向它们的指针。
将引用或指针形参定义为const 来重载函数是合法的。
IO 对象不可复制或赋值。
将一个容器复制给另一个容器时,类型必须精确匹配。
vector<int></int> ivec;
vector<int></int> ivec2(ivec); //ok
vector<double></double>dvec(ivec); //error
list<int></int> ilist(ivec); //error
stack 可用三个做容器;
queue需要基本容器支持push_front 操作,只能用deque 和 list ;
priority_queue 要求基本容器有随机访问功能,只能用vector 和 deque。
关联容器不能通过大小来定义,因为这样的话就无法知道键所对应的值是什么。
构造函数分两个阶段执行:(1)初始化阶段;(2)计算阶段。
必须对const 或引用类型成员以及没有默认构造函数的类类型成员使用初始化式。
在初始化式避免使用成员初始化另一个成员。
当构造函数被声明为explicit ,编译不使用它作为类型转换操作符。
当一个类设为友元,友元类的所有方法可以访问自己的非共有成员。
static 数据成员必须在类定义体外定义。(P401)
const static 数据成员在类的定义体中初始化时,该数据成员仍必须在类定义外定义。(P401)
合成拷贝构造函数直接复制内置类型成员的值,类类型成员使用该类的拷贝构造函数进行复制,数组成员则复制其每一个数组元素。
为了防止复制,可以将拷贝构造函数声明为private ;如果想连友元和成员中的复制也禁止,就可以声明一个private 拷贝构造函数。
重载操作符必须具有一个类类型操作数。
重载操作符并不保证操作数的求值顺序。
(1) =、[]、()、->必须重载为成员函数,否则会编译错误;
(2) 改变对象状态或与给定类型紧密联系的其他一些操作符,如自增、自减和解引用,通常定义为类成员。
(3) 对称的操作符,最好定义为非成员函数。
IO 操作符必须为非成员函数。
一般不要重载合成赋值操作符,&,,,&&和||。
一般为[]定义两个版本:一个为非const 函数并返回引用,一个为const函数并返回cosnt引用。
转换函数operator type():
(1) 不要定义相互转换的类;
(2) 避免到基本类型的转换,如果定义了,不要定义接受算术类型的操作符的重载版本;不要定义转换到一个以上算术类型的转换。
要触发动态绑定,必须满足两个条件:
(1) 只有虚成员函数才能进行动态绑定;
(2) 必须通过基类类型的引用或指针进行函数调用。
如果一个调用省略了具有默认值的实参,则所用的值由调用该函数的类型定义,与对象的动态绑定类型无关。
派生类可以恢复继承成员的访问级别,也仅仅只能“恢复”。
struct 默认成员访问级别为public ,而class 为private;struct 默认继承访问级别为public ,而class 为private。
友元关系不能继承。
构造函数不能是虚函数,赋值操作符不应是虚函数。
运行析构函数或构造函数期间,对象都是不完整的,编译器将对象的类型视为在此期间发生了变化。
如果在构造函数或析构函数中调用虚函数,则运行的是构造函数或析构函数自身类型定义的版本。
第十六章 模板与泛型编程
编写泛型代码的两个重要原则:
(1) 模板形参是const引用;
(2) 函数体中的测试只用比较。
这是为了让实参类型的限制尽可能少。
函数模板的类型形参只支持:
(1) const 转换:接受const 引用或 const 指针的函数模板可以分别用非const对象的引用或或指针来调用,无须产生新的实例化;
(2) 数组或函数到指针的转换。
当抛出一个表达式的时候,被抛出对象的静态编译类型将决定异常对象的类型。
析构函数应该从不抛出异常。
异常类型必须与catch 说明符类型完全匹配,但:
(1) 允许从非const 到 const 引用的转换;
(2) 允许从派生类到基类的转换;
(3) 允许数组和函数到指针的转换。
这是第二次捧起这本巨著来读了,记得2004年是就是靠这书的第二版开始啃C++的,到如今读这本书是仍时时感到不寒而栗。因此把阅读过程中引起了自己注意的部分摘抄了下来,红色部分表示在阅读过程中感到意外或不能理解的,请路过高手解惑!