1) 从逻辑上来讲,size() 成员函数似乎应该返回整形数值,或如 2.2节“建议”中所述的无符号整数。但事实上,size 操作返回的是 string::size_type 类型的值。我们需要对这种类型做一些解释。string 类类型和许多其他库类型都定义了一些配套类型(companion type)。通过这些配套类型,库类型的使用就能与机器无关(machine-independent)。size_type 就是这些配套类型中的一种。它定义为与 unsigned 型(unsigned int 或 unsigned long)具有相同的含义,而且可以保证足够大能够存储任意 string 对象的长度。
2) 通常,C++ 程序中应采用 cname 这种头文件的版本,而不采用 name.h 版本,这样,标准库中的名字在命名空间 std 中保持一致。使用 .h 版本会给程序员带来负担,因为他们必须记得哪些标准库名字是从 C 继承来的,而哪些是 C++ 所特有的。
3) 虽然可以对给定元素个数的 vector 对象预先分配内存,但更有效的方法是先初始化一个空 vector 对象,然后再动态地增加元素。
4) 现代 C++ 程序应尽量使用 vector 和迭代器类型,而避免使用低级的数组和指针。设计良好的程序只有在强调速度时才在类实现的内部使用数组和指针。
5) 数组的维数必须用值大于等于1的常量表达式定义。此常量表达式只能包含整型字面值常量、枚举常量或者用常量表达式初始化的整型 const 对象。非 const 变量以及要到运行阶段才知道其值的 const 变量都不能用于定义数组的维数。
const unsigned sz = get_size(); // const value not known until run time
int vals[sz]; // error: size not known until run time
6) 两个指针减法操作的结果是标准库类型(library type)ptrdiff_t(在VC6.0下其实是int型) 的数据。与 size_t 类型一样,ptrdiff_t 也是一种与机器相关的类型,在 cstddef 头文件中定义。size_t 是 unsigned 类型,而 ptrdiff_t 则是 signed 整型。size_t 类型用于指明数组长度,它必须是一个正数;ptrdiff_t 类型则应保证足以存放同一数组中两个指针之间的差距,它有可能是负数。
7) 在 typedef中使用指针往往会带来意外的结果。下面是一个几乎所有人刚开始时都会答错的问题。假设给出以下语句:
typedef string *pstring;
const pstring cstr;
请问 cstr 变量是什么类型?简单的回答是 const pstring 类型的指针。进一步问:const pstring 指针所表示的真实类型是什么?很多人都认为真正的类型是: const string *cstr; 也就是说,const pstring 是一种指针,指向 string 类型的 const 对象,但这是错误的。错误的原因在于将 typedef 当做文本扩展了。声明 const pstring 时,const 修饰的是 pstring 的类型,这是一个指针。因此,该声明语句应该是把 cstr 定义为指向 string 类型对象的 const 指针,这个定义等价于: string *const cstr。
string s;
typedef string *pstring;
const pstring cstr1 = &s; // written this way the type is obscured
pstring const cstr2 = &s; // all three decreations are the same type
string *const cstr3 = &s; // they're all const pointers to string
8) C++中,规定了操作数计算顺序的操作符还有条件(?:)和逗号操作符。除此之外,其他操作符并未指定其操作数的求值顺序。例如,表达式f1() * f2();
在做乘法操作之前,必须调用 f1 函数和 f2 函数,毕竟其调用结果要相乘。然而,我们却无法知道到底是先调用 f1 还是先调用 f2。
9) 对于内置类型或没有定义默认构造函数的类型,采用不同初始化方式则有显著的差别:
int *pi = new int; // pi points to an uninitialized int
int *pi = new int(); // pi points to an int value-initialized to 0
第一个语句的 int 型变量没有初始化,而第二个语句的 int 型变量则被初始化为0。(注意gcc下可以,VC6.0下不行)
10) 从 istream 中读取数据,并将此表达式作为 while 循环条件:
string s;
while (cin >> s)
这里隐式使用了 IO 标准库定义的类型转换。在与此类似的条件中,求解表达式 cin >> s,即读 cin。无论读入是否成功,该表达式的结果都是 cin。
while 循环条件应为 bool 类型的值,但此时给出的却是 istream 类类型的值,于是 istream 类型的值应转换为 bool 类型。将 istream 类型转换为 bool 类型意味着要检验流的状态。如果最后一次读 cin 的尝试是成功的,则流的状态将导致上述类型转换为 bool 类型后获得 true 值——while 循环条件成立。如果最后一次尝试失败,比如说已经读到文件尾了,此时将 istream 类型转换为 bool 类型后得 false,while 循环条件不成立。