C++ primer plus 第四章:复合类型
一、数组
数组的创建:typeName arrayName[(arraySize)],如 int num[10];
数组的初始化:
int num[10] = {1,3,5,7};
int num[10] = {}; //大括号内不写东西,将会把数组所有元素初始化为0
int num[] = {1,3,5,7}; //方括号内不规定数组大小,将按照大括号内元素个数计算长度
int num[] {1,3,5,7} //可省略等号
int num[] = {1,3,5.0} //该句错误,不允许缩窄操作。
缩窄操作:在赋值过程中发生了浮点数转化成整型的变化,如上一句中5.0赋给整型数组num,这样浮点数将转换成整型存储,发生了缩窄,这样的操作是不允许的。而不同类型的整型之间可能可以相互转换。
数组的赋值:
int num1[10] = {1,3,5,7};
int num2[10] = num1[10]; //不允许这样的操作
二、字符串string类
string类的创建:string str1;
string类的初始化:
string str1 = "The fox";
string str1 = {"The fox"};
string str1 {"The fox"};
string类的赋值、拼接、附加:
string str1 ="The fox";
string str2;
str2 = str1; //赋值
string str3 = str1 + str2; //拼接
str2 + = str1; //附加
计算string对象的长度:int len1 = str1.size()
string类的面向行(即读取到换行符位置,而不是空格)输入:getline(cin,str1);
补充:
char类型的面向行输入有两种方法:
1.getline(字符名,最大输入长度+1)
如:char name[20];
cin.getline(name,20); //将会读取至多19个字符
2.get()
如:cin.get(name1,20); //读取到换行符之前
cin.get(); //读取换行符
cin.get(name2,30); //读取换行符之后的新输入
cstring头文件包含的三个函数:
1.strlen() 计算字符数组中可见字符的长度
对比关键字,sizeof(数组名)将计算数组的长度
2.strcat() 拼接两个字符变量
三、结构struct
结构的定义:
struct people
{
char name[20];
std::string sign; //在struct中使用string要使用命名空间std
float height;
int age;
};
结构的创建:people John;
结构的初始化:
people John {"John","Never give up.",1.78,23};
people John {}; //大括号内没用东西,全部成员将初始化为0
匿名结构:
struct
{
int x;
int y;
}position; //这将创建一个名为position的结构变量,由于该结构没有名字,因此之后将不能被创建
结构的赋值:可以像string类一样赋值,可以作为函数的参数被传递
结构数组:C++将结构看做一种用户自定义的类型,因此也有数组形式。
people wumen[100];
cin >> wumen[0].name; //该句演示了如何访问结构数组中具体哪一个结构的哪一个成员
结构数组的初始化:
people wumen[2]
{
{"Mary",1.68,21},
{"Emma Watson",1.65,30}
}
四、共用体union
共用体的特性是同一时间只能存储某一种类型。
共用体的声明:
union Num
{
int int_Num;
long long_Num;
}; //声明定义了共用体Num可以接受的输入类型有哪几种
共用体的创建:Num id;
共用体的赋值:
if(i == 1)
cin >> id.int_Num = 1000;
else
cin >> id.long_Num = 123123123123;
共用体也可使用匿名形式。
五、枚举enum
枚举是一种创建符号常量的方式,可以代替const。
枚举的声明:enum color {red,yellow,blue}; //默认情况下,color中的各个字符依次代表整数值0~2
枚举的创建:color band;
枚举的赋值:
band = red;
band = 2000; //在没有强制类型转换的情况下,只能将枚举定义的枚举量作为赋值量,因此该句是错的
枚举只有赋值操作,没有算术运算:
band = blue; //可行
++band; //不可行
band = red + blue; //不可行
int colorNum = red;
colorNum = 3+blue; //可行,这样的操作不属于枚举算术运算,而是整型算术运算,因为枚举量blue可以被提升为int类型进行算术运算
显式的设置枚举量的值:
enum bits1 {one = 1,two = 2,four = 4,eight = 8};
enum bits2 {first,two = 2,four =4,last}; //可以只设置部分枚举量的值,这样first被初始化为0,last被初始化为5(比前一个枚举量大1)
enum bits3 {one1 = 1,one2 = 1,one3 = 1}; //可以设置多个相同数值的枚举量
枚举量的取值范围:
bits1 flag = bits(6); //6不在bits1的声明中,但是在bits1的取值范围内,所以这样也是合法的
枚举的取值范围:大于声明中最大值的最小的2的幂再减去1,如bits1中最大值为8,小于等于15(2^4-1),所以bits1的取值范围为0~15
六、指针:使用new在运行时分配内存和释放内存delete
运行时和编译时的区别:运行时就像是出去旅游,到了目的地根据天气、时间等条件决定去哪儿玩,编译时就是无论情况如何按原计划进行。因此在运行时申请内存更灵活。
使用new分配内存:int* p = new int; //告诉程序需要一块适合存储int类型数据的内存,该行为是在运行时(而非编译时)进行的。
堆与栈:一般情况下创建一个变量,程序会在栈中找一块内存用于存储数值,栈是一串连续的地址,原则是先进后出。而使用new创建的变量会在堆中找一块内存,堆的地址是不连续的,一块块内存就像彼此不相关一样堆在一起。
使用new创建动态数组:int* psome = new int[10]; //new运算符返回数组的第一个元素的地址,该句确保分配的内存可以刚好装下长度在10以内的int类型数组(刚好的意思是如果数据没长度没有到10,则分配刚好可以装下该长度数据的内存,最多可以装下长度为10的数据)
使用delete释放内存的原则:
- 不要使用delete释放不是new分配的内存
- 不用使用delete释放同一内存一次以上
- 大多数情况下要和new配套使用
- 使用new为实体分配内存时,使用delete释放,如:delete p
- 使用new为动态数组分配内存是,使用delete[]释放,如:delete [] psome
可以对空指针使用delete
指针和数组的等价性:*psome = &psome[0]
基于上述等价性,对指针进行加减操作是可行的:
psome + 1; //此时psome指向psome[1]的地址,因此,*(psome + 1)= psome[1]
使用new创建动态结构:people *ps = new people;
访问动态结构的成员:ps->height or (*ps).height
补充:
- 关于一些容易混乱的操作:
int* p = new int;
p; //指针p所指向的位置的内容
*p; //指针p所指向的位置的地址
&p; //指针p自身的位置的地址