C++ Primer Plus学习笔记四(第四章)

C++ Primer Plus学习笔记(第四章)续

目录

1)共用体

2)枚举

3)指针

4)使用new来分配内存

5)指针、数组和指针算术

6)C++有3中管理数据内存的方式:自动存储、静态存储和动态存储。

7)数组的替代品:vector和array


1)共用体

a)是一种数据格式,能够存储不同的数据类型,但只能同时存储其中的一种类型。由于每次只能存储一个值,因此它必须有足够的空间来存储最大的成员,所以,共用体的长度为其最大成员的长度。


b)共用体的用途之一是,当数据项使用两种或更多种格式时,可以节省空间。


c)匿名共用体没有名称,其成员将成为位于相同地址处的变量。显然,每次只有一个成员是当前的成员。

union

{

long id_num;

char id_char[20];

}


2)枚举

a)将整数值赋给枚举量,第一个枚举量的值为0,第二个枚举量的值为1,依次类推。

enum spectrum{red,orange,yellow,green,violet,blue};


b)可以用枚举名来声明这种类型的变量。

spectrum band;


c)对于枚举,只定义了赋值运算,没有为枚举定义算术运算。

band=orange;//赋值

band=orange+red;//这是错误的


d)枚举量是整形,可被提升为int类型,但int类型不能自动转换为枚举类型。

int color=blue;

color=3+red;//可以,因为red转换为int类型了


e)可以用赋值运算符来显式地设置枚举量的值。指定的值必须是整数。

enum bits{one=1,two=2,eight=8}


默认情况下第一个是0,后面没有被初始化的枚举量将比前面的枚举量大1。也可以创建多个相同值的枚举量。

enum bigstep{first,second=10,third,third_1=11};


3)指针

a)显示地址时,cout使用十六进制表示法,因为这是常用于描述内存的表示法。在有些系统中,可能不会将两个变量存储在相邻的内存单元中。


b)*运算符被称为间接值或解除引用运算符,将其应用于指针,可以得到该地址处存储的值。mainly是一个指针,mainly表示一个地址,而*mainly表示存储在该地址处的值。*mainly与常规int变量等效。


c)在创建指针时,计算机将分配用来存储地址的内存,但不会分配用来存储指针所指向的数据的内存。为数据提供空间是一个独立的步骤。所以注意:一定要在对指针应用解除引用运算符(*)之前,将指针初始化为一个确定的、适当的地址。


d)指针不是整型,虽然计算机通常把地址当作整数来处理。指针和整数是截然不同的类型。整数可以执行加、减、乘除等运算,而指针描述的是地址,将两个地址相乘没有任何意义。

int *pt;

pt=(int *)0xB8000000;//这样的赋值是有效的


4)使用new来分配内存

a)如果已经声明了相应类型的指针,则可以使用该指针,而不用再声明一个新的指针。为一个数据对象(可以是结构,也可以是基本类型)获得并分配指定内存的通用格式:

typeName  *pointer_name = new typeName;

int *pt= new int;

*pt=1001;


b)new分配的内存块通常与常规变量声明分配的内存块不同。new从被称为堆(heap)或自由存储区的内存区域分配内存。


c)释放指针ps指向的内存,但不会删除指针ps本身。可以将ps重新指向另一个新分配的内存块,一定要配对使用new和delete,否则将发生内存泄露(memory leak)。也就是说,被分配的内存再也无法使用了。如果内存泄露严重,则程序将由于不断寻找更多内存而终止。

int *ps= new int ;

delete ps;


d)不要尝试释放已经释放的内存,这样的结果是不确定的。也不要使用delete来释放声明变量所获得的内存。

int *ps =new int;

delete ps;

delete ps;//释放两次是不正确的


int *pi=&jugs;

delete pi;//不允许这样释放内存


e)不要创建两个指向同一个内存块的指针,因为这将增加错误地删除同一个内存块两次的可能性。另外,只能用delete来释放使用new分配的内存,对空指针使用delete是安全的。


f)静态联编:在编译时给数组分配内存。意味着数组是在编译时加入到程序中。必须在编译程序时指定数组的长度。


动态联编:使用new时,如果在运行阶段需要数组,则创建它,如果不需要,则不创建。还可以在程序运行时选择数组的长度。


g)使用new创建动态数组:只要将数组的元素类型和元素数目告诉new即可。必须在类型名后加上方括号,其中包含元素数目。new运算符返回的是第一个元素的地址。通用格式:

type_name *pointer_name =new type_name [num_elements];


int *psome =new int [10];

delete [ ] psome;


h)总之,使用new和delete应该遵守规则如下:

不要使用delete来释放不是new分配的内存。

不要使用delete释放同一个内存块两次。

如果使用new[ ]为数组分配内存,则应使用delete[ ]来释放。

如果使用new为一个实体分配内存,则应使用delete来释放。

对空指针使用delete是安全的。


5)指针、数组和指针算术

a)将指针变量加1后,增加的量等于它指向的类型的字节数。将指向double的指针加1后,如果系统对double使用8字节存储,则数值将增加8,指向short的指针加1,指针值则加2。


b)对数组应用sizeof运算符得到的是数组的长度,对指针应用sizeof运算符得到的是指针的长度,即使指针指向一个数组。


c)数组的地址:数组名被解析为第一个元素的地址,而对数组名取地址运算得到的是整个数组的地址。

short tell[10];

cout<<tell<<endl;  //&tell[0]数组名-->第一个元素的地址  

cout<<&tell<<endl;  //the whole of array数组名取地址运算-->整个数组的地址


&tell[0](即tell)是一个2字节内存块的地址。而&tell是一个20字节内存块的地址。对表达式tell+1是将地址值加2,而表达式&tell+2是将地址加20。


d)应将内存地址赋给指针。可以对变量名应用&运算符,来获得被命名的内存的地址,new运算符返回未命名的内存的地址。


e)使用方括号数组表示法等同于对指针解除引用。所以,另一种对指针解除引用的方法就是使用数组表示法,如pn[0]与*pn是一样的。绝不要对未被初始化为适当地址的指针解除引用。


6)C++有3中管理数据内存的方式:自动存储、静态存储和动态存储。

a)自动存储:在函数内部定义的常规变量使用自动存储空间,被称为自动变量。意味着他们在所属的函数被调用时自动产生,在该函数结束时消亡。自动变量是一个局部变量,通常存储在栈中。


b)静态存储:是整个程序执行期间都存在的存储方式。使变量成为静态的方式有两种:一种是在函数外面定义它,另一种是在声明变量时使用关键字static。


c)动态存储:new和delete管理了一个内存池,在C++中被称为自由存储空间或堆。该内存池同用于静态变量和自动变量的内存是分开的。


7)数组的替代品:vector和array

a)vector模板类:类似于string类,也是一种动态数组。可以在运行阶段设置vector对象的长度,可以在末尾附加新数据,也可以在中间插入新数据。


b)vector类确实使用new和delete来管理内存,但是是自动完成的。要使用vector对象,必须包含头文件<vector>,还包含在名称空间std中。


c)标准格式:vector<typeName> vt(n_elem);

如:vector<int> ai(4);


d)模板类array:包含头文件<array>,包含在名称空间std中。array对象的长度是固定的,使用栈来创建。格式:

array<typeName, n_elem> arr;

如:array<double, 4> ai={1.2, 1.3,  2.2,  3.3};


e)可以使用vector和array对象的成员函数at()。

如:a2.at(1)=2.3;  //a2[1]=2.3



第四章(完)




你可能感兴趣的:(C++,c)