sizeof 运算符指出整个数组的长度;
strlen()函数返回的是存储在数组中的字符串的长度,而不是数组本身的长度。另,strlen()只计算可见的字符,而不把空字符计算在内。
cin使用空白(空格、制表符和换行符)来确定字符串的结束位置。即cin在获取字符串数组输入时只读取一个单词。
读取一行字符串的方法 P78
<istream>:
① getline(): cin.getline(name,20); getline()函数每次读取一行,通过换行符来确定行尾,但不保存换行符。相反,在存储字符串时,用空字符来替代换行符。
② get(): 并不再读取并丢弃换行符,而是将其留在输入队列中。
cin.get(name, NameSize).get();
cin.get(dessert, Size);
注:如果使用的是cin.get(name,Size),则编译器知道是要将一个字符串放入数组中,因而将使用适当的成员函数。如果使用的是cin.get(),则编译器知道是要读取一个字符。
③ get()与getline()相比的好处:更细致,可以通过判断下一个输入字符是换行符还是别的字符来判断停止读取的原因是已经读取了整行还是因为数组已满。
④ 当读取空行时:
get()读取空行后将设置失效位(failbit)。这意味着接下来的输入将被中断,但可用下面的命令来恢复输入:cin.clear();
⑤ 若输入字符串比分配的空间长:则getline()和get()将把余下的字符留在输入队列中,而getline()还会设置失效位。
⑥ 若混合输入字符串和数字,为防止输入数字后的换行符被赋给字符串,应当:
cin>>year; cin.get(); cin.getline(address,80);
或: (cin>>year).get(); //(or (cin>>year).get(ch);)
共用体union p94:
能够存储不同的数据类型,但只能同时存储其中的一种类型。
常用于(但并非只能用于)节省内存。另外,共用体常用于操作系统数据结构或硬件数据结构。
使用new来分配内存 p102:
typeName * pointer_name = new typeName;
使用delete释放内存
① Delete将释放指针指向的内存,但不会删除指针本身。
② 一定要配对的使用new和delete,否则将发生内存泄漏(memory leak)
③ 不能使用delete来释放声明变量所获得的内存。
④ 只能用delete来释放使用new分配的内存。然而,对空指针使用delete是安全的。
使用new来创建动态数组 p104
① 如果程序只需要一个值,则可能会声明一个简单变量。通常,对于大型数据(如数组、字符串和结构),应使用new。例如,假设要编写一个程序,它是否需要数组取决于运行时用户提供的消息。如果通过声明来创建数组,则在程序被编译时将为它分配内存空间。不管程序最终是否使用数组,数组都在那里,它占用了内存。在编译时给数组分配内存被称为静态联编(static binding),意味着数组是在编译时加入到程序中的。但使用new时,如果在运行阶段需要数组,则创建它;如果不需要,则不创建。还可以在程序运行时选择数组的长度。这被称为动态联编(dynamic binding),意味着数组是在程序运行时创建的。这种数组叫做动态数组。使用静态联编时,必须在编写程序时指定数组的长度;使用动态联编时,程序将在运行时确定数组的长度。
② 使用new来创建动态数组。
a) 使用new创建的数组,应使用delete[] psome; 来释放
b) 使用new和delete时,应遵循以下规则:
i. 不要使用delete释放不是new分配的内存
ii. 不要使用delete释放同一内存块两次
iii. 如果使用new[]为数组分配内存,则应使用delete[]来释放
iv. 如果使用new[]为一个实体分配内存,则应使用delete(没有方括号)来释放
v. 对空指针应用delete是安全的
c) 为数组分配内存的通用格式:
type_name *pointer_name = new type_name[num_elements];
③ 使用动态数组
a) C和C++内部都使用指针来处理数组。数组和指针基本等价。
b) 不能修改数组名的值,但指针是变量,因此可以修改它的值。
c) 将指针变量加1后,其增加的值等于指向的类型占用的字节数。
d) 对数组应用sizeof运算符得到的是数组的长度,而对指针应用sizeof得到的是指针的长度,即使指针指向的是一个数组。
P108
指针和数组:
① 将指针变量加1后,其增加的值等于指向的类型占用的字节数。
② 在很多情况下,可以相同的方式使用指针名和数组名。对于它们,可以使用数组方括号表示法,也可以使用解除引用运算符(*),它们都表示地址。区别之一是,可以修改指针的值,而数组名是常量。
③ 对数组应用sizeof运算符得到的是数组的长度,而对指针应用sizeof得到的是指针的长度,即使指针指向的是一个数组。这种情况下,C++不会将数组名解释为地址。
④ short tell[10];
cout<<tell<<endl; //displays&tell[0]
cout<<&tell<<endl; //displaysaddress of whole array
从数字上说,这两个地址相同。但从概念上说&tell[0](即tell)是一个2字节内存块的地址,而&tell是一个20字节内存块的地址。因此,表达式tell+1将地址值加2,而表达式&tell+2将地址加20.换句话说,tell是一个short指针(*short),而&tell是一个这样的指针,即指向包含20个元素的short数组(short(*)[20])。
总之,使用new来创建数组以及使用指针来访问不同的元素很简单,只要把指针当做数组名对待即可。
数组的替代品:vector 和 array
模板类vector:
模板类vector类似于string类,也是一种动态数组。可在运行阶段设置vector对象的长度,可在末尾附加新数据,还可在中间插入新数据。基本上,它是使用new创建动态数组的替代品。实际上,vector类确实使用new和delete来管理内存,但这种工作是自动完成的。
① 要使用vector对象,必须包含头文件vector。
② Vector包含在名称空间std中。
③ 模板使用不同的语法来指出它存储的数据类型。
④ Vector类使用不同的语法来指定元素数。
⑤ 一般而言,下面的声明创建一个名为vt的vector对象,它可以存储n_elem个类型为typeName的元素:
vector<typeName> vt(n_elem);
其中n_elem可以是整型常量,也可以是整型变量。
⑥ #include<vector>
模板类array(C++11)
① C++新增了模板类array,它也位于名称空间std中。与数组一样,array对象的长度也是固定的,也使用栈(静态内存分配),而不是自由存储区,因此其效率与数组相同,但更方便,更安全。
② 要创建array对象,需包含头文件array:
#include<array>
③ array<typeName, n_elem> arr;
④ n_elem不能是变量