第四章 复合类型

4.1 数组

  • 数组是一种数据格式,能够存储多个同类型的值,数组声明的通用格式 typeName arrayName[arraySize] 表达式arraySize指定元素数目,必须是整型常数或const值,也可以是常量表达式,即其中所有的值在编译时都是已知的
  • 编译器不会检测使用的下标是否有效,如果将一个值赋给不存在的元素month[101],编译器并不会指出错误,但是程序运行后,这种赋值可能引发问题,它可能破坏数据或代码,也可能导致程序异常终止
  • sizeof运算符用于数组名,得到的是整个数据中的字节数,如果用于数组元素,则得到的将是元素的长度
  • 初始化数组时,提供的值可以少于数组的元素数目,如果只对数组的一部分进行初始化,则编译器将其他元素设置为0,只要显式地将第一个元素初始化为0,然后编译器将其他元素都初始化为0

4.2 字符串

  • 字符串是存储在内存的连续字节中的一系列字符,存储在连续字节中的一系列字符意味着可以将字符串存储在char数组中,其中每个字符都位于自己的数组元素中,C风格字符串具有一种特殊的性质,以空字符结尾,空字符被写作\0,ASCII码为0,用来标记字符串的结尾

  • 字符串常量【char bird[11] = “Mr Li”】,用引号括起来的字符串隐式地包括结尾的空字符,在确定存储字符串所需的最短数组时,别忘了将结尾的空字符计算在内,字符串常量不能与字符常量互换

  • 拼接字符串常量,任何两个由空白分隔的字符串常量都将自动拼接成一个,拼接时不会在被连接的字符串之间添加空格,第二个字符紧跟在第一个字符后面,第一个字符串中的\0字符将被第二个字符串的第一个字符取代

  • getline()函数读取整行,通过回车键输入的换行符来确定输入结尾,通过使用cin.getline(),两个参数,第一个用来存储输入行的数组的名称,第二个用来读取字符数,参数20,读取19,余下用于存储自动在结尾处添加的空字符【cin.getline(arr,ArSize)】

  • get并不再读取并丢弃换行符,而是将其留在输入队列中【该变体同getline()类似】,使用不带任何参数的cin.get()可读取下一个字符(即使是换行符)
    -【cin.get(name,Arsize)
    cin.get()
    cin,get(dessert,Arsize)】或【cin.get(name,Arsize).get()】

  • 当getline()或get()读取空行时,下一条输入语句将在前一条getline()或get()结束读取的位置开始读取,但当前做法,当get()读取空行后将设置施小炜,接下来的输入将被阻断,恢复输入:cin.clear()

4.3 String类简介
要使用String类,必须在程序中包含头文件string,string类位于名称空间std中,必须提供一条using编译指令
#include
using namespace std;

  • string对象使用方式同使用字符数据相同,主要区别, 可以将string对象声明为简单变量,而不是数组,类设计让程序能够自动处理string的大小,使用string对象更方便,也更安全
  • 使用string类时,某些操作比使用数组更简单【不能将一个数据赋给另一个数据,但可以将一个string对象赋给另一个string对象】
  • string类减缓了字符串合并操作,可以使用字符串+=将两个string对象合并起来,还可以使用运算符+=将字符串附件到string对象的末尾
  • 使用函数strcpy()将字符串赋值到字符数组中,使用函数strcat()将字符串附加到字符数组末尾
  • 确定字符串中字符数的方法 str1.size() strlen(charr1)

4.4 结构简介
结构是用户定义的类型,结构声明定义了这种类型的数据属性,可以使用成员运算符(.)来访问各个成员,访问成员函数一样

4.5 共用体

  • 共用体是一种数据格式,它能够存储不同的数据类型,但只能同时存储其中的一种类型,结构可以同时存储int,long,double,但共用体只能存储int,long或double
  • 共用体的用途之一是数据项使用两种或更多中格式(但不会同时使用)时,可节省空间,匿名共用体没有名称,其成员将位于相同地址处的变量,显然,每次只有一个成员时当前的成员
struct widget
{
	char brand[20];
	int type;
	union 
	{
		long id_num;
		char id_char[20];
	}
	...
	widget prize;
	...
	if(prize.type == 1)
		cin>>prize.id_num;
	else
		cin>>prize.id_char;
	
}

4.6 枚举

enum spectrum
{
	red
	orange
	yellow
	ble
}

spectrum被称为枚举,red/orange等作为符号常量,对应整数值0-3,这些常量叫做枚举量

  • 默认情况下,将整数值赋给枚举量,第一个枚举量的值为0,以此类推,在不进行强制类型转换的情况下,只能将定义枚举时使用的枚举量赋给这种枚举的变量
  • 对于枚举,之定义了赋值运算符。具体地说,没有为枚举定义算法运算,枚举量是整型,可被提升为int类型,但int类型不能自动转换为枚举类型,如果int值是有效的,可以通过强制类型转换,将它赋给枚举变量
  • 可以使用赋值运算符来显示地设置枚举量的值,指定的值必须是整数,也可以显式地定义一些枚举量的值,first在默认情况下为0,后面没有被初始化的枚举量的值将比前面的枚举量大1,最后,可以创建多个值相同的枚举值
  • C++现在通过强制类型转换,增加了可赋给枚举变量的合法值,每个枚举值都有取值范围,通过强制类型转换,可以将取值范围中的任何整数赋给枚举变量,即使这个值不是枚举值
  • 4.7 指针和自由存储空间
    ①声明初始化指针
  • 指针是一个变量,其存储的是值的地址,而不是值本身,如何找到常规变量,只需对变量应用地址运算符&
  • *运算符称为间接值或解除引用运算符,将其应用于指针,可以得到该地址处存储的值
  • int ptr 强调ptr是int类型的值,int* ptr 强调ptr是指向int的指针【int a =5; int * ptr =&a,将pt(而不是*pt)的值设置为&higgens】
    ②指针的危险
  • 一定要在对指针应用解除引用运算符(*)之前,将指针初始化为一个确定的,适当的地址【long * fellow,*fellow = 223323】
  • 要将数字值作为地址来使用,应通过强制类型转换将数字转换为适当的地址类型,赋值语句的两边都是整数的地址
    ③使用new分配内存
  • 【int * pn =new int】new int告诉程序,需要适合存储int的内存,new运算符根据类型来确认需要多少字节的内存,然后,找到这样的内存并返回其地址,new分配的内存块通常与常规变量声明分配的内存块不同。【栈与堆】
    ④使用delete释放内存
  • delete运算符,使得在使用完内存后,能够将其归还给内存池,这是通向有效地使用内存的关键一步,使用delete时,后面加上指向内存块的指针【int * ps = new int; delete ps; 这将是否ps指向的内存,但不会删除指针ps本身】,只能用delete释放使用new分配的内存,对空指针使用delete时是安全的,另外,一般来说,不要创建两个指向同一个内存块的指针,因为这将增加错误地删除同一个内存块两次的可能性
    ⑤使用new创建动态数组
    int * psome =new int [10];
    delete [] psome;
    方括号告诉程序,应释放整个数组,而不仅仅是指针指向的元素
    使用new/delete遵循规则
  • 不要使用delete释放不是new分配内存
  • 不要使用delete释放同一块内存两次
  • 使用new[]为数组分配内存,使用delete[]来释放
  • 对空指针应用delete是安全的
    数组名和指针之间的根本差别:不能修改数组名的值,但指针是变量,可以修改它的值
    p3 = p3 +1

4.8 指针,数组和指针算术

  • 指针和数组基本等价的原因在于指针算术和C++内存处理数组的方式,整数变量+1以后,其值增加1,指针变量+1以后,增加的量等于它指向类型的字节数
  • 对数组应用sizeof运算符得到的是数组的长度,对指针应用sizeof得到的是指针的长度,即使指针指向的是一个数组
  • 【short tell[10] cout<<tell<<endl; cout<<&tell<<endl】 从数字上说,这两个地址相同;但是从概念上说,&tell[0](即tell)是一个2字节内存块的地址,而&tell是一个20字节内存块的地址
  • 【char flower[10] =“rose” cout<<flower<<endl】总之,给cout提供一个字符的地址,则它将从该字符开始打印,知道遇到空字符为止
  • 应使用strcpy()或strncpy(),而不是赋值运算符来讲字符串赋给数组
  • 创建动态结构时【inflatable * ps = new inflatable】,不能将成员运算符句点用于结构名,因为这种结构没有名称,只是知道它的地址,箭头成员运算符(—>)

①自动存储,静态存储,动态存储

  • 自动存储,函数内部定义的常规变量使用自动存储空间,被称为自动变量,意味着他们在所属函数被调用时自动产生,在该函数结束时消亡,自动变量存储在栈中,执行代码块时,变量依次加入到栈中,离开代码块时,按照相反顺序释放变量,后进先出,执行过程中,栈不断地增大和缩小
  • 静态存储是整个程序执行期间都存在的存储方式,一种是在函数外面定义它,一种是在声明变量时使用static
  • 动态存储,new/delete,管理了一个内存池,被称为自由存储空间或堆

4.10 数组的替代品

-vector类确实使用new和delete来管理内存,但这种工作是自动完成的,要使用vector对象,必须包含头文件vector,vector包含在名称空间std中,因此可使用using编译指令,using声明或std::vector

-vector类的功能比数组强大,但付出的代价时效率较低,如果需要长度固定的数组,使用数组是更佳的选择,但代码是不那么方便和安全。鉴于如此,C++11新增了模板类array,同数组一样,array对象长度固定,使用栈(静态内存分配),而不是自由存储区,其效率与数组相同,但更方便,安全

#include

using namespace std;
array<int, 5> ai;
array<double, 4> ad={1,2,3,4};

模板array<typename, n_elem> arr; 与创建vector对象不同,n_elem不能是变量

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值