之前阅读时没有及时总结,现在慢慢补上。
第1章 快速入门
main 函数在很多方面都比较特别,其中最重要的是每个C++程序必须含有 main 函数,且 main 函数是(唯一)被操作系统显示调用的函数。
main 函数的返回值必须是 int 型。
endl 是一个特殊值,称为操纵符(manipulator),将它写入输出流时,具有输出换行的效果,并刷新与设备相关联的缓冲区(buffer)。通过刷新缓冲区,用户可立即看到写入到流中的输出。
C++中通过定义类来定义自己的数据结构。
标准库的头文件用尖括号< >括起来,非标准库的头文件(自定义头文件)用双引号" "括起来。
第2章 变量和基本类型
要获得无符号型则必须指定该类型为unsigned。
以0(零)开头的字面值整数常量表示八进制,以 0x 或 0X 开头的表示十六进制。
为了兼容C语言,C++所有的字符串字面值都由编译器自动在末尾添加一个空字符(' ')。
在C++中理解“初始化不是赋值”是必要的:初始化指创建变量并给它赋初始值,而赋值则是擦除对象的当前值并用新值代替。
内置类型变量是否自动初始化取决于变量定义的位置。在函数体外定义的变量都初始化成0,在函数体里定义的内置类型变量不进行自动初始化。
变量的定义用于为变量分配存储空间,还可以为变量指定初始值。
声明用于向程序表明变量的类型和名字。定义也是声明:当定义变量时我们声明了它的类型和名字。可以通过使用 extern 关键字声明变量名而不定义它。
任何在多个文件中使用的变量都需要有与定义分离的声明。在这种情况下,一个文件含有变量的定义,使用该变量的其他文件则包含该变量的声明(而不是定义)。
与其他变量不同,除非特别说明,在全局作用域声明的 const 变量是定义该对象的文件的局部变量。此变量只存在于那个文件中,不能被其他文件访问。通过指定 const 变量为 extern ,就可以在整个程序中访问 const 对象。
引用只是对象的另一个名字。
const 引用是指向 const 对象的引用。例:
const int ival = 1024; const int &refVal = ival ; //ok int &ref2 = ival ; //error
枚举的定义包括关键字 enum ,其后是一个可选的枚举类型名,和一个用花括号括起来、用逗号分开的枚举成员列表。
enum open_modes { input, output, append };
默认地,第一个枚举成员赋值为0,后面的每个枚举成员赋的值比前面的大1。
用来初始化枚举成员的值必须是一个常量表达式。
不能改变枚举成员的值。枚举成员本身就是一个常量表达式。
如果使用 class 关键字来定义类,那么定义在第一个访问标号前的任何成员都隐式指定为private ;如果使用struct 关键字,那么这些成员都是public。
设计头文件时,应使其可以多次包含在同一源文件中,这一点很重要。我们必须保证多次包含同一头文件不会引起该头文件定义的类和对象被多次定义。使得头文件安全的通用做法,是使用预处理器定义头文件保护符。头文件保护符用于避免在已经见到头文件的情况下重新处理该头文件的内容。
为了避免名字冲突,预处理器变量经常用全大写字母表示。
#ifndef SALESITEM_H #define SALESITEM_H // Define```````` #endif
第3章 标准库类型
任何存储 string 的 size 操作结果的变量必须为 string::size_type 类型。特别重要的是,不要把 size 的返回值赋给一个 int 变量。
保存一个 string 对象 size 的最安全的方法就是使用标准库类型 string::size_type。
当进行 string 对象和字符串字面值混合连接操作时,+操作符的左右操作数必须至少有一个是 string 类型的:
string s1="hello"; string s2="world"; string s3=s1+","; //ok string s4="hello"+", " //error string s5=s1+", "+"world"; //ok string s6="hello"+", "+s2; //error
vector 元素的位置从0开始。
必须是已存在的元素才能用下标操作符进行索引。通过下标操作进行赋值时,不会添加任何元素。
所谓的“缓冲区溢出”错误就是对不存在的元素进行下标操作的结果。
由于容器的 end 操作返回的迭代器不指向任何元素,因此不能对它进行解引用或自增操作。
容器定义了一种名为 const_iterator 的类型,该类型只能用于读取容器内元素,但不能改变其值。
任何改变 vector 长度的操作都会使已存在的迭代器失效。例如,在调用 push_back 之后,就不能再信赖指向 vector 的迭代器的值了。
两个迭代器相加的操作是未定义的。
第4章 数组和指针
区别:数组的长度是固定的,数组一经创建,就不允许添加新的元素。指针则可以像迭代器一样用于遍历和检查数组中的元素。
现代C++程序应尽量使用 vector 和迭代器类型,而避免使用低级的数组和指针。设计良好的程序只有在强调速度时才在类实现的内部使用数组和指针。
与 vector 类型相比,数组的显著缺陷在于:数组的长度是固定的,而且程序员无法知道一个给定数组的长度。数组没有获取其容量大小的 size 操作,也不提供 push_back 操作在其中自动添加元素。如果需要更改数组的长度,程序员只能创建一个更大的新数组,然后把原数组的所有元素复制到新数组空间中去。
非 const 变量以及要到运行阶段才知道其值的 const 变量都不能用于定义数组的维数。
与 vector 不同,一个数组不能用另外一个数组初始化,也不能将一个数组赋值给另一个数组。
C++提供了一种特殊的指针类型 void*,它可以保存任何类型对象的地址。
void* 指针只支持几种有限的操作:与另一个指针进行比较;向函数传递 void* 指针或从函数返回 void* 指针;给另一个 void* 指针赋值。不允许使用 void* 指针操纵它所指向的对象。
不能使用 void* 指针保存 const 对象的地址,而必须使用 const void* 类型的指针保存 const 对象的地址。
在使用下标访问数组时,实际上是对指向数组元素的指针做下标操作。只要指针指向数组元素,就可以对它进行下标操作。例:
int ia[]={0,2,4,6,8}; int *p=&ia[2]; int j=p[1]; //ok, j=ia[3] int k=p[-2]; //ok, k=ia[0]
指针和 const 限定符
1、指向 const 对象的指针
如果指针指向 const 对象,则不允许指针来改变其所指的 const 值。为了保证这个特性,C++语言强制要求指向 const 对象的指针也必须具有 const 特性:
const double *cptr ;
2、const 指针
除指向 const 对象的指针外,C++语言还提供 const 指针———本身的值不能修改:
int errNumb=0; int *const curErr=&errNumb;const 指针的值不能修改,这就意味着不能使 curErr 指向其他对象。
与任何 const 量一样,const 指针也必须在定义时初始化。
字符串字面值的类型就是 const char 类型的数组。
牢记字符串必须以结束符 null 结束:
char ca[]={'C','+','+'}; //not null-terminated cout << strlen(ca) << endl; //disater: ca isn't null-terminated
动态数组的定义:
数组变量通过指定类型、数组名和维数来定义。而动态分配数组时,只需指定类型和数组长度,不必为数组对象命名,new 表达式返回指向新分配数组的第一个元素的指针:
int *pia = new int[10];此 new 表达式分配了一个含有10个 int 型元素的数组,并返回指向该数组第一个元素的指针,此返回值初始化了指针 pia 。
new 表达式需要指定指针类型以及在方括号中给出的数组维数,该维数可以是任意的复杂表达式。创建数组后,new 将返回指向数组第一个元素的指针。在自由存储区中创建的数组对象是没有名字的,程序员只能通过其地址间接访问堆中的对象。
第5章 表达式
第6章 语句
switch (ch) { case 'a': ++aCnt; // not have a break statement case 'e': ++eCnt; // not have a break statement case 'i': ++iCnt; // not have a break statement case 'o': ++oCnt; // not have a break statement case 'u': ++uCnt; // not have a break statement }对于上面的代码,假设 ch 的值是 ‘i’,程序从 case 'i' 后面的语句开始执行,iCnt 的值加1。但是,程序的执行并没有在这里停止,而是越过case 标号继续执行,同时将 oCnt 和 uCnt 的值都加了1。
第7章 函数
int gcd(int v1, int v2) { while (v2) { int temp=v2; v2=v1%v2; v1=temp; } return v1; }
函数声明
void print(int *array, int size);变量可以在头文件中声明,而在源文件中定义。同理,函数也应当在头文件中声明,并在源文件中定义。
局部对象
内联函数
重载函数
const int* p=&a; int const* p=&a;上面这两个功能相同,都是指针指向的内容不能被修改。
int* const p=&a;指针p本身的值不能被修改。