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不能是变量