一 概述
从第二部分我们了解到堆的好处是可以存储比较大的数据,而且存储的数据只要不是程序员手动将其释放,那么就会永远保存在堆中。不像栈,存储的数据只在函数内有效,超出函数就消失了。也不像全局变量,保存的数据只有程序结束才会释放,而且很容易被修改
二 指针与堆
2.1 概念
- 既然了解了它的许多好处,接下来的问题就是如何使用它,我们知道堆是一大堆不连续的内存区域,在系统中由链表将它们串接起来,它不像栈,你可以为它其中的某个内存单元命名,为了数据隐秘起见,堆中的每个内存单元都是匿名的,因此你必须现在堆中申请一个内存单元的地址,然后把它保存在一个指针中。这样你只有使用该指针才可以访问到该内存单元的数据。
2.2 示例
- 换句话说,你不知道安徽出版社的地址,但是你从朋友那里得到了它的电话号码,然后你给他们打电话,如果对方接起电话,那么你就成功了访问了安徽出版社。这时即使你忘记了安徽出版社电话号码,即使对方已挂断电话,你也可以按下重播键,再次通过电话访问安徽出版社,因为电话已经记录了你上次拨打的号码。在这种情况下,电话号码就相当于地址,你不需要知道地址,因为电话已经帮你记录下了地址,你只需要按下重播键,电话这个指针就会根据重播键中记忆的电话号码自动指向安徽出版社,然后你就可以访问安徽出版社了
- 再打个比方,你要去博物馆,但是不知道地址,这时你就可以叫个出租车带你去博物馆,你不需要知道博物馆的地址,出租车司机的脑子中保存着博物馆的地址,你只需要告诉他你要去博物馆,那么他马上就会拉着你去博物馆。在这个例子中,出租车司机脑子中记录的博物馆的地址相当于堆中某单元的内存地址,你不需要知道堆中该单元的地址,你只需要类似出租车司机一样的指针,那么你就可以访问堆中该单元的数据了
2.3 好处
- 采取这种匿名的内存访问方式,而不是使用公开的全局变量,好处是只有使用特定的指针才能访问特定的数据。这样就避免了任何试图修改它的非法操作
2.4 如何做
- 要做到这一点,我们首先得创建一个堆,然后定义一个指向该堆的指针。这样就只能通过该指针才能访问堆中的数据。
- 在C++中使用关键字new创建一个堆并分配内存,在new后面跟一个要分配的对象类型,编译器根据这个类型类分配内存。
三 代码及结果分析
3.1 代码
1 2 3 4 5 6 7 8 9
| #include<iostream> using namespace std; int main() { int *p = new int; *p = 1; cout << *p; return 0; }
|
3.2 输出结果
3.3 代码说明
- int *p;这一行定义了一个指向整型的指针变量p
- p=new int;这一行用new在堆中创建一个int类型的内存区域,然后将该区域的内存地址赋给指针变量p。这样p所指向的就是这块新建的内存区域。在这里要注意的是,new int 在堆中被变异去分配了4个字节的空间。假如是new double那么就要被分配8个字节的内存空间
- 上面两句可以合并为一句:int *p=new int;
- 这样在定义指针p的同时,初始化了它的值为一个在堆中新建的int型存储区的内存地址。你可以像使用普通指针一样使用它,并把赋给它所指向的内存空间
四 总结
- 由于你的计算机的内存是有限的,因此可能会出现没有足够内存而无法满足new的情况,在这种情况下,new会返回0,该值被赋给指针后,那么该 指针就是一个空指针,空指针不会指向有效数据。
- new除了返回空值之外,还会引发异常,在后面的异常错误处理中将会讲解