📄 第20章 指针二 为指针分配和释放空间.htm
字号:
border=0> </P></TD>
<TD align=middle width="40%"><IMG height=65
src="第20章 指针二 为指针分配和释放空间.files/ls20.h6.gif" width=78 align=absMiddle
border=0>
<P><SPAN lang=zh-cn>(任务管理显示我的机器使用了207兆的内存)</SPAN></P></TD></TR>
<TR>
<TD width="60%">
<P align=center><SPAN lang=zh-cn>第二步:分配了100兆的内存</SPAN>
<P align=center><IMG height=36
src="第20章 指针二 为指针分配和释放空间.files/ls20.h7.gif" width=301 align=middle
border=0> </P></TD>
<TD align=middle width="40%"><IMG height=65
src="第20章 指针二 为指针分配和释放空间.files/ls20.h8.gif" width=82 align=middle
border=0>
<P align=center>(<SPAN lang=zh-cn>多出了100M</SPAN>)</P></TD></TR>
<TR>
<TD width="60%">
<P align=center><SPAN lang=zh-cn>第三步:又释放出这100兆</SPAN>
<P align=center><IMG height=41
src="第20章 指针二 为指针分配和释放空间.files/ls20.h9.gif" width=199 align=middle
border=0> </P></TD>
<TD align=middle width="40%"><IMG height=66
src="第20章 指针二 为指针分配和释放空间.files/ls20.h10.gif" width=78 align=middle
border=0>
<P align=center>(<SPAN
lang=zh-cn>回到207兆</SPAN>)</P></TD></TR></TBODY></TABLE>
<P>
<P><B><SPAN lang=zh-cn>注意:使用</SPAN> new <SPAN lang=zh-cn>得来的空间,必须用</SPAN>
delete <SPAN lang=zh-cn>来释放;使用</SPAN> new [] <SPAN
lang=zh-cn>得来的空间,必须用</SPAN> delete [] <SPAN
lang=zh-cn>来释放。彼此之间不能混用。</SPAN></B>
<P>
<P><SPAN lang=zh-cn>用</SPAN> new [] <SPAN
lang=zh-cn>分配出连续空间后,指针变量“指向”该空间的首地址。</SPAN>
<P>
<H4><B><A name=20.3.3>20.3.3</A> <SPAN
lang=zh-cn>详解指向连续空间的指针</SPAN></B></H4>
<P>
<P>在<SPAN lang=en-us> </SPAN>通过<SPAN lang=en-us> new [] </SPAN>指向连续空间以后,p
就变得和一个一维数组很是类似。我们先来复习一下数组相关知识。
<P>
<P>假设是这么一个数组:
<P>
<P><SPAN lang=en-us>int arr[20];</SPAN>
<P>
<P>则<SPAN lang=en-us>arr </SPAN>的内存示意图为(为了不太占用版面我缩小了一点):
<P align=center>
<P align=center><IMG height=268
src="第20章 指针二 为指针分配和释放空间.files/ls20.h4.gif" width=261 border=0>
<P align=center><SPAN lang=en-us>(</SPAN>数组<SPAN lang=en-us> arr
</SPAN>的内存示意<SPAN lang=en-us>)</SPAN>
<P align=center>
<P>和指针变量相比,<SPAN lang=en-us>
</SPAN>数组没有一个单独的内存空间而存放其内存地址。即:指针变量p是一个独立的变量,只不过它的值指向另一段连续的内存空间;而数组arr,本身代表的就是一段连续空间。
<P>
<P>如果拿房间来比喻。指针和数组都是存放地址。只不过,指针是你口袋里的那本通讯录上写着的地址,你可以随时改变它的内容,甚至擦除。而数组是你家门楣上钉着的地址,你家原来是“复兴路甲108号”,你绝对不能趁月黑天高,把它涂改为“唐宁街10号”。
<P>
<P>数组是“实”的地址,不能改变。当你和定义一个数组,则这个数组就得根据它在内存中的位置,得到一个地址,如上图中的“<SPAN
lang=en-us>0x1A000000</SPAN>”。只要这个数组存在,那么它终生的地址就是这个值。
<P>
<P>指针是一个“虚”的地址,可以改变地址的值。当你定义一个指针变量,这个变量占用4个字节的内存,你可以往这4字节的内存写入任意一个值,该值被当成一个内存地址。比如,你可以写入上面的“<SPAN
lang=en-us>0x1A000000</SPAN>”<SPAN
lang=en-us>,</SPAN>此时,指针p指向第一个元素。也可以改为“<SPAN
lang=en-us>0x1A00000</SPAN>3”,此时,指针p指向第二个元素。
<P>
<P>所以,当p通过<SPAN lang=en-us> new [] </SPAN>指向一段连续空间的结果是,p 是一个指向数组的指针,而<SPAN
lang=en-us>*p</SPAN>是它所指的数组。
<P>
<P>我们来看实例,首先看二者的类似之处。下面左边代码使用数组,右边代码使用指针。
<P>
<TABLE id=AutoNumber1 style="BORDER-COLLAPSE: collapse"
borderColor=#111111 cellSpacing=0 cellPadding=0 width="100%" border=1>
<TBODY>
<TR>
<TD width="50%">数组</TD>
<TD width="50%">指针<SPAN lang=en-us> (</SPAN>通过<SPAN lang=en-us> new
[] </SPAN>所得<SPAN lang=en-us>)</SPAN></TD></TR>
<TR>
<TD width="50%"><SPAN lang=en-us>//</SPAN>定义<SPAN
lang=en-us>:</SPAN>
<P><SPAN lang=en-us>int arr[</SPAN>20<SPAN lang=en-us>];
</SPAN></P></TD>
<TD width="50%"><SPAN lang=en-us>//</SPAN>定义:
<P><SPAN lang=en-us>int* p = new int[20];</SPAN></P></TD></TR>
<TR>
<TD width="50%">
<P><SPAN lang=en-us>//</SPAN>让第一个元素值为100:</P>
<P><SPAN lang=en-us>arr[0] = 100;</SPAN></P>
<P> </P></TD>
<TD width="50%"><SPAN lang=en-us>//</SPAN>让第一个元素值为100:
<P><SPAN lang=en-us>p[0] = 100;</SPAN></P></TD></TR>
<TR>
<TD width="50%"><SPAN lang=en-us>//</SPAN>让后面19个元素值分别为其前一元素加<SPAN
lang=en-us> </SPAN>5<SPAN lang=en-us>0</SPAN>:
<P><SPAN lang=en-us>for (int i = 1; i < 20; i++)</SPAN></P>
<P><SPAN lang=en-us>{</SPAN></P>
<P><SPAN lang=en-us> arr[i] = arr[i-1] + 50;</SPAN></P>
<P><SPAN lang=en-us>}</SPAN></P></TD>
<TD width="50%"><SPAN lang=en-us>//</SPAN>让后面19个元素值分别为其前一元素加<SPAN
lang=en-us> </SPAN>5<SPAN lang=en-us>0</SPAN>:
<P><SPAN lang=en-us>for (int i = 1; i < 20; i++)</SPAN></P>
<P><SPAN lang=en-us>{</SPAN></P>
<P><SPAN lang=en-us> p[i] = p[i-1] + 50;</SPAN></P>
<P><SPAN lang=en-us>}</SPAN></P></TD></TR>
<TR>
<TD width="50%"><SPAN lang=en-us>//</SPAN>输出所有元素:
<P><SPAN lang=en-us>for (int i = 0; i < 20; i++)</SPAN></P>
<P><SPAN lang=en-us>{</SPAN></P>
<P><SPAN lang=en-us> cout << arr[i] <<
endl;</SPAN></P>
<P><SPAN lang=en-us>}</SPAN></P></TD>
<TD width="50%"><SPAN lang=en-us>//</SPAN>输出所有元素:
<P><SPAN lang=en-us>for (int i = 0; i < 20; i++)</SPAN></P>
<P><SPAN lang=en-us>{</SPAN></P>
<P><SPAN lang=en-us> cout << p[i] <<
endl;</SPAN></P>
<P><SPAN lang=en-us>}</SPAN></P></TD></TR>
<TR>
<TD width="50%"><SPAN lang=en-us>//</SPAN>也可以不用[],而通过+号来得到指定元素:
<P><SPAN lang=en-us>//</SPAN>当然,对于数组,更常用的还是 [] 操作符。</P>
<P><SPAN lang=en-us>cout << *(arr + 0) << endl;
//*(arr+0) </SPAN>等于<SPAN lang=en-us> *arr</SPAN></P>
<P><SPAN lang=en-us>cout << *(arr + 1) <<
endl;</SPAN></P>
<P><SPAN lang=en-us>cout << *(arr + 1) <<
endl;</SPAN></P>
<P> </P>
<P>输出结果:</P>
<P style="LINE-HEIGHT: 100%"><FONT color=#ffffff><SPAN lang=en-us
style="BACKGROUND-COLOR: #000000"> 100 </SPAN></FONT></P>
<P style="LINE-HEIGHT: 100%"><FONT color=#ffffff><SPAN lang=en-us
style="BACKGROUND-COLOR: #000000"> 150 </SPAN></FONT></P>
<P style="LINE-HEIGHT: 100%"><FONT color=#ffffff><SPAN lang=en-us
style="BACKGROUND-COLOR: #000000"> 200 </SPAN></FONT></P></TD>
<TD width="50%"><SPAN lang=en-us>//</SPAN>也可以不用[],而通过+号来得到指定元素:
<P>//其实,对于指针,这样的+及-操作用得还要多点。</P>
<P><SPAN lang=en-us>cout << *(p + 0) << endl; //*(p + 0)
</SPAN>等于<SPAN lang=en-us> *p</SPAN></P>
<P><SPAN lang=en-us>cout << *(p + 1) << endl;</SPAN></P>
<P><SPAN lang=en-us>cout << *(p + 1) << endl;</SPAN></P>
<P> </P>
<P>输出结果:</P>
<P style="LINE-HEIGHT: 100%"><FONT color=#ffffff><SPAN lang=en-us
style="BACKGROUND-COLOR: #000000"> 100 </SPAN></FONT></P>
<P style="LINE-HEIGHT: 100%"><FONT color=#ffffff><SPAN lang=en-us
style="BACKGROUND-COLOR: #000000"> 150 </SPAN></FONT></P>
<P style="LINE-HEIGHT: 100%"><FONT color=#ffffff><SPAN lang=en-us
style="BACKGROUND-COLOR: #000000"> 200
</SPAN></FONT></P></TD></TR></TBODY></TABLE>
<P>
<P>
<P><B>当指针变量 P 通过<SPAN lang=en-us> new [] </SPAN>指向一连续的内存空间<SPAN
lang=en-us>:</SPAN></B>
<P><B>1、<SPAN lang=en-us>p[N] </SPAN>得到第N个元素 (<SPAN lang=en-us>0 <=
</SPAN>N <SPAN lang=en-us>< </SPAN>元素个数)<SPAN
lang=en-us>;</SPAN>2、<SPAN lang=en-us>*(p + N) </SPAN>同样得到第N个元素 (<SPAN
lang=en-us>0 <= </SPAN>N <SPAN lang=en-us>< </SPAN>元素个数)</B>
<P>如<SPAN lang=en-us> p[0] </SPAN>或<SPAN lang=en-us> *(p + 0)
</SPAN>得到内存空间第<SPAN lang=en-us>0</SPAN>个元素;
<P>
<P>把上面右边代码中的大部分<SPAN lang=en-us> p </SPAN>替换为<SPAN lang=en-us>
arr</SPAN>,则和左边代码变得一模一样。
<P>
<P>下面再来比较二者的不同。
<P>
<TABLE id=AutoNumber2 style="BORDER-COLLAPSE: collapse"
borderColor=#111111 cellSpacing=0 cellPadding=0 width="96%" border=1>
<TBODY>
<TR>
<TD width="48%">数组</TD>
<TD width="52%">指针</TD></TR>
<TR>
<TD width="48%"><SPAN lang=en-us>//</SPAN>定义并且初始化<SPAN
lang=en-us>:</SPAN>
<P><SPAN lang=en-us>int arr[</SPAN>20<SPAN lang=en-us>] =
{0,1,2,3,4,5,6,7,8,9,0,</SPAN>……<SPAN lang=en-us>,19}; </SPAN></P>
<P><SPAN lang=en-us></SPAN> </P></TD>
<TD width="52%"><SPAN lang=en-us>//</SPAN>定义、并且生成空间,但不能直接初始空间的内容:
<P><SPAN lang=en-us>int* p = new int[20] {0,1,2,3,4 </SPAN>……<SPAN
lang=en-us>} //<FONT color=#ff0000> </SPAN>错<SPAN
lang=en-us>!</SPAN></FONT></P>
<P> </P>
<P><SPAN lang=en-us>//</SPAN>只得通过循环一个个设置:</P>
<P><SPAN lang=en-us>for (int i = 0; i < 20; i++)</SPAN></P>
<P><SPAN lang=en-us>{</SPAN></P>
<P><SPAN lang=en-us> p[i] = i;</SPAN></P>
<P><SPAN lang=en-us>}</SPAN></P></TD></TR>
<TR>
<TD width="48%">//不能通过对数组本身<SPAN lang=en-us> </SPAN>+<SPAN
lang=en-us> </SPAN>或<SPAN lang=en-us> </SPAN>-<SPAN lang=en-us>
</SPAN>来改变数组的位置:
<P><SPAN lang=en-us>arr = arr + 1; // </SPAN><FONT
color=#ff0000>错<SPAN lang=en-us>!</SPAN></FONT></P>
<P><SPAN lang=en-us>cout << *arr << endl;</SPAN></P>
<P> </P>
<P><SPAN lang=en-us>arr++; // </SPAN><FONT
color=#ff0000>错<SPAN lang=en-us>!</SPAN></FONT></P>
<P><SPAN lang=en-us>cout << *arr << endl;</SPAN></P>
<P> </P>
<P><SPAN lang=en-us>arr--; // </SPAN><FONT
color=#ff0000>错<SPAN lang=en-us>!</SPAN></FONT></P>
<P><SPAN lang=en-us>cout << *arr << endl;</SPAN></P>
<P> </P>
<P>输出结果<SPAN lang=zh-cn>:</SPAN></P>
<P><FONT color=#808080><SPAN lang=zh-cn>无,</SPAN>因为程序<SPAN
lang=zh-cn>有语法错误,</SPAN>通<SPAN lang=zh-cn>不</SPAN>过编译。</FONT></P></TD>
<TD width="52%"><SPAN lang=en-us>//</SPAN>可以通过<SPAN lang=en-us>
</SPAN>+<SPAN lang=en-us> </SPAN>或<SPAN lang=en-us> </SPAN>-<SPAN
lang=en-us> </SPAN>操作直接改变指针:
<P><SPAN lang=en-us>p = p + 1;</SPAN></P>
<P><SPAN lang=en-us>cout << *p << endl;</SPAN></P>
<P> </P>
<P><SPAN lang=en-us>p++;</SPAN></P>
<P><SPAN lang=en-us>cout << *p << endl;</SPAN></P>
<P> </P>
<P><SPAN lang=en-us>p--;</SPAN></P>
<P><SPAN lang=en-us>cout << *p << endl;</SPAN></P>
<P> </P>
<P>输出结果:</P>
<P style="LINE-HEIGHT: 100%"><FONT color=#ffffff><SPAN lang=en-us
style="BACKGROUND-COLOR: #000000"> 1 </SPAN></FONT></P>
<P style="LINE-HEIGHT: 100%"><FONT color=#ffffff><SPAN lang=en-us
style="BACKGROUND-COLOR: #000000"> 2 </SPAN></FONT></P>
<P style="LINE-HEIGHT: 100%"><FONT color=#ffffff><SPAN lang=en-us
style="BACKGROUND-COLOR: #000000"> 1 </SPAN></FONT></P></TD></TR>
<TR>
<TD width="48%">//<SPAN lang=zh-cn>释放空间:</SPAN>
<P><SPAN lang=zh-cn>//数组所带的空间由系统自动分配及回收</SPAN></P>
<P><SPAN lang=zh-cn>//无须也无法由程序来直接释放。</SPAN></P></TD>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -