本系列只用于查漏补缺,强化理解
4.7 指针和自由存储空间
指针的声明
指向double的指针和指向int的指针并不是同一种类型,但两个变量的长度是相同的。
在声明语句中初始化指针:
int higgens = 5;
int * pt = &higgens;
等同于
int higgens = 5;
int * pt;
pt = &higgens
危险操作
所以一定要在对指针使用*运算符前,将指针初始化为确定的地址。
指针类型和整型
指针不是数字,我们不可以把整数赋值给指针
(但是C语言可以)
在C++中我们需要进行类型转换
int * pt;
pt = (int *) 0xB8000000; // types match
New和Delete
new
目的:我们可以在程序运行时,分配给未命名的内存以存储值
类似于C语言中的malloc但是new是更不错的方法。
new使用例子:
int * pt = new int;
内部过程:new int告诉程序需要存贮int类型的数据,所以他将根据int类型的字节大小,返回一个合适内存的地址。最后将地址赋值给pt
我们可以像使用变量一样使用*pt
cout << *pt;
cout << sizeof(*pt);
当然,sizeof(pt)和sizeof(*pt)是不一样的,pt和&
pt也是不一样的
分配错误返回0
delete
int * ps = new int;
//...
delete ps;
delete ps将会释放ps指向的内存,但是ps这个指针还可以指向别的内存块。
禁忌:
- 不要尝试已经delete过的内存块。
- delete只用来释放new分配的内存(不过可以对空指针使用)
delete释放的既然是内存,那就意味我们也可以用别的指针释放这个内存。不过一般不要创建两个指向同一内存的指针
new创建动态数组
这才是new的用武之地!
普通创建数组会在编译时分配空间,使用new可以在运行时定于数组并确定长度
//创建
int * psome = new int [10];
//....
delete [] psome;
移动数组指针之后,若要delete数组,需要将指针移回第一位。例如下图红色箭头部分。
4.8 指针算术
指针增加1后,增加的量等于指向的类型的字节数。
对数组名应用sizeof函数得到的是数组长度,对指针应用得到的是指针长度。
以下是演示如何使用给不同形式的字符串的例子。
上图中,为cout提供一个char数组的数组名时,输出为该字符串,所以若想输出地址,则需进行类型转换(int*)。
使用new创建动态结构时需要使用->访问成员的原理如下
4.10 数组的替代品
讨论之前我们简单了解自动存储,静态存储,和动态存储
- 自动存储:在函数内部定义的变量,是局部变量,会自动消亡。存储在栈中。自动添加和删除的占用内存是连续的。
- 静态存储:是整个程序执行期间都存在的存储方式。
- 动态存储:使用new和delete进行管理的内存池。存储在自由存储空间(堆),添加和删除的内存不连续。
我们稍微引入vector,array的知识
对比一下array和vector的创建方式
array<int, 4> a1;
vector<int> v1(4);
以后还会详细讲到array。array有一个优势是可以直接赋值
array<int, 4> a1 = {1,2,3,4};
array<int, 4> a2;
a2 = a1;