数组是“实”的地址,不能改变。当你和定义一个数组,则这个数组就得根据它在内存中的位置,得到一个地址,如上图中的
“0x1A000000”。只要这个数组存在,那么它终生的地址就是这个值。
指针是一个“虚”的地址,可以改变地址的值。当你定义一个指针变量,这个变量占用4个字节的内存,你可以往这4字节的内存写入任意一个值,该值被当成一个内存地址。比如,你可以写入上面的“0x1A000000”,此时,指针p指向第一个元素。也可以改为“0x1A000003”,此时,指针p指向第二个元素。
所以,当p通过 new [] 指向一段连续空间的结果是,p 是一个指向数组的指针,而*p是它所指的数组。
我们来看实例,首先看二者的类似之处。下面左边代码使用数组,右边代码使用指针。
白话C++
当指针变量 P 通过 new [] 指向一连续的内存空间:
1、p[N] 得到第N个元素(0 <= N < 元素个数);
2、*(p + N) 同样得到第N个元素(0 <= N < 元素个数)
如 p[0] 或 *(p + 0) 得到内存空间第0个元素;
把上面右边代码中的大部分 p 替换为 arr,则和左边代码变得一模一样。
白话C++
下面再来比较二者的不同。
白话C++
关于指针本身的 + 和 - 操作,请复习上一章相关内容。
接下来的问题也很重要。
20.4 delete/delete[] 的两个注意点
指针通过 new 或 new[] ,向系统“申请”得到一段内存空间,我们说过,这段内存空间必须在不需要将它释放了。有点像人类社会的终极目标“共产主义”下的“按需分配”。需要了就申请,不需要了,则主动归还。
现在问题就在于这个“主动归还”。当然,指针并不存在什么思想觉悟方面的问题,说光想申请不想归还。真正的问题是,指针在某些方面的表现似乎有些像“花心大萝卜”。请看下面代码,演示令人心酸的一幕。
/*
初始化 p ----- p 的新婚
通过 new ,将一段新建的内存“嫁给”指针p
这一段分配的内存,就是p的原配夫妻
*/
int* p = new int[100];
/*
使用 p ----- 恩爱相处
N 多年恩爱相处,此处略去不表
*/
……
/*
白话C++
p 改变指向 ---- 分手
*/
int girl [100]; //第三者出现
p = girl; //p 就这样指向 girl
/*
delete [] p ---- 落幕前的灾难
终于有一天,p老了,上帝选择在这一时刻
惩罚他
*/
delete [] p;
扣除注释,上面只有4行代码。这4行代码完全符合程序世界的宪法:语法。也就是说对它们进行编译,编译器会认为它们毫无错误,轻松放行。
但在灾难在 delete [] p 时发生。
我们原意是要释放 p 最初通过 new int[100]而得到的内存空间,但事实上,p那时已经指向girl[100]了。结果,第一、最初的空间并没有被释放。第二、girl[100] 本由系统自行释放,现在我们却要强行释放它。
20.4.1 一个指针被删除时,应指向最初的地址
当一个指针通过 +,- 等操作而改变了指向;那么在释放之前,应确保其回到原来的指向。
比如:
白话C++
int* p = new int[3];
*p = 1;
cout << *p << endl;
p++; //p的指向改变了,指向了下一元素
*p = 2;
cout << *p << endl;
//错误的释放:
delete [] p;
在 delete [] p 时,p指向的是第二个元素,结果该释放将产生错位:第一个元素没有被释放,而在最后多删除了一个元素。相当你盖房时盖的是前3间,可以在拆房时,漏了头一间,从第二间开始拆起,结果把不是你盖的第4房间倒给一并拆了。
如何消除这一严重错误呢?
第一种方法是把指针正确地"倒"回原始位置:
p--;
delete [] p;
但当我们的指针指向变化很多次时,在释放前要保证一步不错地一一退回,会比较困难。所以另一方法是在最初时“备份”一份。在释放时,直接释放该指针即可。
int* p = new int[3];
int* pbak = *p; //备份
//移动 p
……
白话C++
//释放:
delete [] pbak;
由于pbak正是指向p最初分配后的地址,我们删除pbak,就是删除p最初的指向。此时我们不能再删除一次p。这也就引出new / delete 及 new[] / delete[] 在本章的最后一个问题。
20.4.2 已释放的空间,不可重复释放
第一种情况,错了最直接:
int* p = new int(71);
cout << *p << endl;
delete p; //OK!
delete p; //ERROR! 重复删除p
当然,如果同一指针在delete之后,又通过new 或 new[] 分配了一次内存,则需要再删除一次:
int* p = new int(71);
cout << *p << endl;
delete p; //OK!
...
p = new int(81);
delete p; //OK!
...
p = new int[10];
for (int i=0; i<10; i++)
百度搜索“77cn”或“免费范文网”即可找到本站免费阅读全部范文。收藏本站方便下次阅读,免费范文网,提供经典小说医药卫生第20章 指针 二 为指针分配和释放空间(3)在线全文阅读。
相关推荐: