1. 我们编写的程序以及所保存的程序数据在计算机的内存中是以二进制位序列的方式存放的,位(bit)是含有0或1值的一个单元。
2. 一个字节由8位构成,而一个字由32位构成,或者说是4个字节。
3. 类型抽象使我们能够对一个定长的位序列进行有意义的解释。
4. C++提供了一组预定义的数据类型,如字符型、整型、浮点型,以及一组基本的数据抽象,如string、vector和复数。它还提供了一组操作符(或称运算符),如加、减、等于、小于操作符等来操纵这些类型。C++还为程序流控制提供了为数不多的一组语句,如while循环和if语句。这些要素构成了一个符号系统。
CH3
1. C++预定义了一组数值数据类型,可以用来表示整数、浮点数和单个字符。
2. 字符型char,通常用来表示单个字符和小整数;整型int、短整型short、长整型long,分别代表不同长度的整数值;浮点型float、双精度double和长双精度long double分别表示单精度浮点数、双精度浮点数和扩展精度的浮点数值。
3. char、short、int和long称为整值类型(integral type),整值类型可以有符号,也可以无符号;在有符号类型中,最左边的位是符号位,余下的位代表数值;在无符号类型中,所有的位都表示数值,如果符号位被置为1,数值被解释成负数,如果是0,则为正数。
4. 当一个数值,例如1,出现在程序中时,它被称为文字常量(literal constant)。文字常量是不可寻址的(nonaddressable)。
5. 整数文字常量可以被写成十进制,八进制或者十六进制的形式。在缺省情况下,整型文字常量被当作是一个int型的有符号值。
6. 可以在文字常量后面加一个L或l(字母L的大写形式或者小写形式),将其指定为long类型;可以在整型文字常量的后面加上u或U将其指定为一个无符号数;还可以指定无符号long型的文字常量。
7. 浮点型文字常量可以被写成科学计数法形式或普通的十进制形式。使用科学计数法,指数可写作“e”或“E”;浮点型文字常量在缺省情况下被认为是double型,单精度文字常量由值后面的“f”或“F”来标示;类似地,扩展精度中值后面跟的“l”或“L”来指示(注意,f、F、l、L后缀只能用在十进制形式中)。
8. 单词true和false是bool型的文字常量;可打印的文字字符常量可以写成用单引号括起来的形式;一部分不可打印的字符、单引号、双引号以及反斜杠可以用转义序列来表示(转义序列以反斜杠开头)。
9. 字符文字前面可以加“L”,这称为宽字符文字,类型为wchar_t。
10. 字符串文字常量由零个或多个用双引号括起来的字符组成。不可打印字符可以由相应的转义序列来表示,而一个字符串文字可以扩展到多行。在一行的最后加上一个反斜杠,表明字符串文字在下一行继续。
11. 字符串文字的类型是常量字符数组,它由字符串文字本身以及编译器加上的表示结束的空(null)字符构成。空字符是C和C++用来标记字符串结束的符号。
12. 在许多实际开发环境中,成功的主要评价标准是最后的结果,至于对处理过程的讨论则很可能被视为学术气、不切实际,总是得不到重视。
13. 变量为我们提供了一个有名字的内存存储区,可以通过程序对其进行读、写和处理;C++中的每个符号变量都与一个特定的数据类型相关联,这个类型决定了相关内存的大小、布局、能够存储在该内存区的值的范围以及可以应用其上的操作集。也可以把变量说成对象(object)。
14. 变量和文字常量都有存储区,并且有相关的类型。区别在于变量是可寻址的(addressable),对于每一个变量,都有两个值与其相关联:一是它的数据值(存储在某个内存地址中,右值),二是它的地址值——即存储数据值的那块内存的地址(左值)。
15. 变量的定义会引起相关内存的分配,因为一个对象只能有一个位置,所以程序中的每个对象只能被定义一次。
16. 对象声明(declaration)的作用是使程序知道该对象的类型和名字,它由关键字extern以及跟在后面的对象类型和对象的名字构成。一个程序只能包含一个对象的一个定义,但它可以包含任意数目的对象声明。
17. 变量名,即变量的标识符(identifier),可以由字母、数字以及下划线字符组成。它必须以字母或下划线开头,并且区分大写字母和小写字母。
18. 命名对象的习惯:1)对象名一般用小写字母;2)标识符一般使用助记的名字(能够对程序中的用法提供提示的名字);3)对于多个词构成的标识符,习惯上,一般在每个词之间加一个下划线,或内嵌的每个词第一个字母大写。
19. 一个简单的对象定义由一个类型指示符后面跟一个名字构成,以分号结束。当同类型的多个标识符被定义的时候,我们可以在类型指示符后面跟一个由逗号分开的标识符列表。
20. 如果一个变量是在全局域(global scope)内定义的,那么系统会保证给它提供初始值0;如果变量是在局部域(local scope)内定义的,或是通过new表达式动态分配的,则系统不会向它提供初始值0,这些对象被称为是未初始化的(uninitialized)。
21. 一个被声明了初始值的对象也被称为已经初始化的(initialized),C++支持两种形式的初始化:第一种形式是使用赋值操作符的显式语法形式;第二种形式是一种特殊的构造函数语法,可将对象初始化为0。
22. 不同数据类型的指针之间的区别之处在于指针所指的对象的类型上。指针的类型可以指示编译器怎样解释特定地址上内存的内容,以及该内存区域应该跨越多少内存单元。
23. 通过在标识符前加一个解引用操作符(*)来定义指针。指针不能持有非地址值,指针不能被初始化或赋值为其他类型对象的地址值。
24. 空(void*)类型指针可以被任何数据指针类型的地址值赋值(函数指针不能赋值给它)。void*表明相关的值是个地址,但该地址的对象类型不知道。
25. C++提供了解引用操作符(dereference operator)*来间接地读和写指针所指向的对象。
26. 指针可以让它的地址值增加或减少一个整数值,这类指针操作被称为指针的算术运算(pointer arithmetic)。
27. 字符串被存储在一个字符数组中,一般通过一个char*类型的指针来操纵它。
28. 程序将永远执行下去或者由系统终止它,这样的循环被称作无限循环(infinite loop)。
29. 像这样的程序修正通常被称作补丁(patch)——把某些东西伸展开以便补上现有程序中的洞。
30. C++标准库提供了字符串类抽象的一个公共实现:1)支持用字符序列或第二个字符串对象来初始化一个字符串对象;2)支持字符串之间的拷贝;3)支持读写访问单个字符;4)支持两个字符串的相等比较;5)支持两个字符串的连接;6)支持对字符串长度的查询;7)支持字符串是否为空的判断。
31. const类型限定修饰符把一个对象转换成一个常量(constant)。在程序中任何改变这个值的企图都将导致编译错误,因此它被称为是只读的(read-only)。
32. 因为常量在定义后就不能被修改,所以它必须被初始化。未初始化的常量定义将导致编译错误。
33. const对象的地址只能赋值给指向const对象的指针,但是指向const对象的指针可以被赋以一个非const对象的地址。
34. 引用(reference),有时候又称为别名(alias),它可以用作对象的另一个名字;通过引用我们可以间接地操纵对象,使用方式类似于指针。
35. 引用类型由类型标识符和一个取地址操作符来定义,引用必须被初始化。一旦引用已经定义,它就不能再指向其他的对象。
36. 引用的所有操作实际上都被应用在它所指的对象身上,包括取地址操作符。每个引用的定义必须以取地址操作符开始。
37. const引用可以用不同类型的对象初始化(只要能从一种类型转换到另一种类型即可),也可以是不可寻址的值,如文字常量。
38. 编译器为了实现引用,必须生成一个临时对象,引用实际上指向该对象,但用户不能访问它。
39. 指针和引用有两个主要区别:引用必须总是指向一个对象(如果用一个引用给另一个引用赋值,那么改变的是被引用的对象而不是引用本身);引用之间的赋值(赋值之后,引用仍然指向原来的对象)。
40. 实际的C++程序很少使用指向独立对象的引用类型,引用类型主要被用作函数的形式参数。
41. 布尔型对象可以被赋以文字值true或false。虽然布尔类型的对象也被看作是一种整数类型的对象,但是它不能被声明为signed、unsigned short或long。
42. 当表达式需要一个算术值时,布尔对象和布尔文字都被隐式地提升成int。 false变成0,而true变成1。
43. 算术值和指针值也能隐式地被转换成布尔类型的值,0或空指针被转换成false,所有其他的值都被转换成true。
44. 枚举(enumeration)不但定义了整数常量,而且还把它们组成一个集合。枚举成员(enumerator)代表了能用来初始化和赋值变量的值的全集。
45. 不能做到的是打印枚举成员的实际枚举名,一种解决方案是定义一个由枚举成员的值索引的字符串数组。不能使用枚举成员进行迭代。
46. 枚举类型用关键字enum,加上一个自选的枚举类型名来定义,类型名后面跟一个用花括号括起来的枚举成员列表,枚举成员之间用逗号分开。在缺省情况下,第一个枚举成员被赋以值0,后面的每个枚举成员依次比前面的大1。也可以显式地把一个值赋给一个枚举成员。
47. 可以定义枚举类型的对象,它可以参与表达式运算,也可以作为参数传递给函数。枚举类型的对象能够被初始化,但是只能被一个相同枚举类型的对象或枚举成员集中的某个值初始化或赋值。
48. 在必要时,枚举类型会自动被提升成算术类型。
49. 数组是一个单一数据类型对象的集合,其中单个对象并没有被命名,但是我们可以通过它在数组中的位置对它进行访问。这种访问形式被称作索引访问(indexing)或下标访问(subscripting)。
50. 数组定义由类型名、标识符和维数组成;维数指定数组中包含的元素的数目,它被写在一对方括号里边;维数值必须是常量表达式。
51. 数组可以被显式地用一组数来初始化,这组数用逗号分开,放在大括号中;被显式初始化的数组不需要指定维数值,编译器会根据列出来的元素的个数来确定数组的维数。
52. 字符数组可以用一个由逗号分开的字符文字列表初始化,文字列表用花括号括起来,或者用一个字符串文字初始化;但是,注意这两种形式不是等价的,字符串常量包含一个额外的终止空字符。
53. 一个数组不能被另外一个数组初始化,也不能被赋值给另外一个数组;而且,C++不允许声明一个引用数组(即由引用组成的数组)。要把一个数组拷贝到另一个中去,必须按顺序拷贝每个元素。
54. C++没有提供编译时刻或运行时刻对数组下标的范围检查。
55. 可以定义多维数组,每一维用一个方括号对来指定;一个二维数组的第一维被称作行(row)维,第二维称作列(column)维。
56. 数组标识符代表数组中第一个元素的地址,它的类型是数组元素类型的指针。
57. 数组元素遍历则可以通过下标操作符来实现,或者也可以通过直接操作指针来实现数组元素遍历。
58. 使用vector有两种不同的形式,即所谓的数组习惯和STL习惯。
59. 可以用下标操作符访问vector的元素,vector的元素被初始化为与其类型相关的缺省值,算术和指针类型的缺省值是0;对于class类型,缺省值可通过调用这类的缺省构造函数获得。
60. 对于内置数组,可以显式地把数组的元素初始化为一组常量值;可以将vector初始化为一个已有数组的全部或一部分,只需指定希望被用来初始化vector 的数组的开始地址以及数组最末元素的下一位置来实现例。
61. 复数(complex number)类是标准库的一部分,每个复数都有两部分:实数部分和虚数部分。
62. typedef机制为我们提供了一种通用的类型定义设施,可以用来为内置的或用户定义的数据类型引入助记符号;这些typedef名字在程序中可被用作类型标识符。
63. typedef定义以关键字typedef开始,后面是数据类型和标识符;这里的标识符即typedef名字,它并没有引入一种新的类型,而只是为现有类型引入了一个助记符号。
64. 当一个对象的值可能会在编译器的控制或监测之外被改变时,那么该对象应该声明成volatile。
65. pair类也是标准库的一部分,它使得我们可以在单个对象内部把相同类型或不同类型的两个值关联起来。可以用成员访问符号(member access notation)访问pair中的单个元素。
66. 类的定义由关键字class开始,后面是一个标识符,该标识符也被用作类的类型指示符。一个类包括公有的(public)操作部分和私有的(private)数据部分,这些操作被称为该类的成员函数(member function)或方法(method),它们定义了类的公有接口(public interface)——即,用户可以在该类对象上执行的操作的集合。
67. 根据被传递给构造函数的参数类型来判断构造函数的应用,这种构造函数被称为拷贝构造函数(copy constructor),因为它用另一个对象的拷贝来初始化一个对象。
68. 类的成员函数可以被定义在类的定义中,也可以定义在外面;在类定义之外定义的成员函数不但要告诉编译器它们的名字、返回类型、参数表,而且还要说明它们所属的类。
69. 可能要频繁调用的小函数应声明成内联(inline)函数,内联函数在每个调用点上被展开,因此这样做可以消除函数调用相关的额外消耗。
70. 析构函数由类名前面加一个波浪号(~)来标识。