C++复合类型
3种复合类型:
数组、结构、指针
1 数组
声明数组:
short months[3] = {0,1,2};
创建数组:
数组初始化规则:
默认元素的值为0
如果元素个数为空,编译器会计算元素个数。
数组初始化方法:
可以省略=
{}中可以没有内容
不能缩窄转换:类型失去精度、超过取值范围等
模板类:
vector、array
2 字符串
C++处理字符串的方式:
1是C-风格字符串:以空字符\0结尾
2是string类库
char cat[4] = {'c','a','t','\0'};
char cat[] = "cat";
数组初始化为字符串
字符串常量和字符常量不能互换。
如:char s = 'S',是83的另一种写法;只有单个字符;
char s = "S",错误表示,"S"表示字符串所在的内存地址;由字符S和字符\0组成
拼接字符串:
空白(空格、制表符、换行符)
数组使用字符串:
1是将数组初始化为字符串常量
char name[2] = "xm";
2是将键盘或文件输入读入到数组中
一个单词
char name1[2];
cin >> name1;//使用空白(空格、\t、\n)确定字符串结束的位置;长度可能大于目标数组;仍然留有换行符,所以需要在读取地址之前先读取并丢弃换行符。
cin.get();
或者:(cin >> name1).get();
strlen()是数组中字符串的长度,只计算可见字符,不包含空字符。
使用\0截断字符串
一个句子
cin.getline(name, 20):通过回车键输入的换行符确定输入结尾。
cin.get(name, 20).get():第一次换行符留在输入队列;再次无参数cin.get()认为已到达行尾。
拼接:
cin.getline(name, 20).getline(name1, 20);
空行或其他问题:
输入空行后,get()会设置失效位,接下来的输入被阻断,使用cin.clear()恢复
输入字符串大于分配空间,Dgetline()会设置失效位,关闭后面的输入。
混合输入字符串和数字:
在读取地址之前先读取并丢弃换行符即可。
3 String
可以使用C-风格字符串来初始化string对象、可以使用cin将键盘输入存储到string对象中、可以使用cout来显示对象、使用数组表示法访问存储在string对象中的字符。
string相比数组:
更方便,更安全(长度)。
可以将一个string对象赋给另一个string对象,数组不可以。
string拼接:
+
+=
其他操作:
strcpy(charray, string)//字符串复制到字符数组
strcat(char1, string)//字符串附加到字符数组末尾
str.size();//长度
strlen(str);//长度,如果第一个空字符的出现位置是随机的,则数组长度可能和给定的不同。
新的一行:getline(cin, str);没有指出字符串长度的参数,string对象会自动调整大小。
字面值:
原始字符串:"( )" 用作定界符,并使用前缀R来标识。使用R"+*( )+*"标识开头和结尾。
标准字符串时:需要使用\来转义。
4 结构
struct关键字
用户自定义的类型,结构声明定义了数据属性。
结构描述的组成部分
外部声明和内部声明:
注意:
不提倡使用外部变量,但提倡使用外部结构声明。
可以使用赋值运算符将结构赋给另一个同类型的结构。
结构名称可以省略,直接创建结构变量,但是不推荐。
结构成员可以指定占用的特定位数,这个成员被称为位字段。
结构数组:
数组的元素为结构;
5 共用体
union关键字
能够存储(声明)不同的数据类型,但是只能同时存储其中的一种,所以长度为最大成员的长度;
常用于操作系统数据结构或硬件数据结构。
作用:
使用多种格式时,可以节省空间;
匿名共同体(anonymous union)
没有名称
6 枚举
enum工具,可以代替const,允许定义新类型;
默认情况,将整数值赋给枚举量;会递增枚举量的值;枚举量的值可以取取值范围内的数;
取值范围:最大值:大于最大值、最小的2的幂,减1;最小值:大于0时:0;小于0时:类似于最大值;
枚举名可以声明变量,
只定义了赋值运算符,没有算术运算。
枚举可以转换为int,但是int不能转换为枚举。
枚举常被用来定义相关的符号常量,而不是新类型。
7 指针
存储的是值的地址;常规变量的地址为派生量。
显示地址:&,十六进制表示法;
定义指针,*为间接值或者解除引用运算符。
OOP:强调运行阶段(动态联编 dynamic binding)。使用new请求正确数量的内存以及使用指针跟踪新分配的内存的位置。
硬币的两面表示变量和指针变量
指针声明必须指定指针指向的数据的类型:
字节数不同,内部格式不同,
指针存储地址
注意:
地址的长度或值不能指示关于变量的长度或类型的任何信息,也不能指示该地址上有什么内容。
创建指针时,计算机会分配用来存储地址的内存,不会分配用来存储指针指向的数据的内存。如果初始化指针变量时,会导致一些bug。
指针描述的是位置,不知道对应的值的类型,强转时可能出现问题。
new分配内存:
指针真正用于在运行阶段分配未命名的内存已存储值。
int *pn = new int;
程序员告诉new,需要为哪种数据类型分配内存;new将找到一个长度正确的内存块,并返回该内存块的地址。将地址赋给指针。但是pn指向的内存没有名称时,pn指向一个数据对象(东西)即为数据项分配的内存块。
常规变量的值被存储在栈的内存区域中,new则是从堆或者自由存储区的内存区域分配内存。
当计算机内存不足时,new会引发异常。
delete释放内存:
使用完内存后,可以使用delete将内存归还或释放给内存池。但是不会删除指针本身。可以通过new重新给指针分配内存,否则内存泄露。
声明变量(没有new)的指针不能使用delete释放。
new创建动态数组:
new真正应用于大型数据:数组,字符串和结构;
int *psome = new int[10];//返回第一个元素的地址,指向内存块中的第一个元素。
delete [] psome;
使用new和delete的规则:
访问元素时:指针可以当数组名,psome[1]即可。
psome+1:指针psome增加的是指向的类型的字节数,所以指向下一个元素。即取值时取到下一个位置的值。
8 指针、数组和指针算术
指针和数组基本等价的原因:指针算术和内部处理数组的方式。
指针值可以修改,数组名是常量,被解释为第一个元素的地址,整个数组的地址是&。
sizeof,指针数组是指针的长度,变量数组是数组的长度。
C++将数组名解释为地址。
指针加法
new创建动态结构:
运行时为结构分配所需的空间。new用于结构由创建结构和访问成员组成。
inflatable *ps = new inflatable;
成员运算符句点不能用于结构名。结构没有名称,只知道地址。使用运算符:->,用于指向结构的指针。ps -> price 是被指向结构的price成员。
或者:(*ps).price//*ps是结构本身。
标识结构成员
自动存储、静态存储和动态存储:
C++管理数据内存的方式:
自动存储、静态存储和动态存储、线程存储
自动存储:函数内部定义的常规变量使用自动存储空间,被称为自动变量(局部变量)。函数调用时自动产生,函数结束时消失。存储在栈中。
静态存储:变量在函数外定义;声明变量时使用static。
动态存储:new和delete运算符。可以在一个函数中分配内存,另一个函数中释放。但是自由存储可能不连续,跟踪新分配内存的位置时困难。
9 数组的替代品vector和array
vector
动态数组,包含在std中,堆
array
长度固定,栈,一个array对象可以赋给另一个array对象
两者使用at()时捕获索引异常,程序默认中断。