⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 第20章 指针二 为指针分配和释放空间.htm

📁 用非常通俗的语言介绍了C++和C
💻 HTM
📖 第 1 页 / 共 5 页
字号:
      lang=zh-cn>则程序无法通过编译,报错:“不能将</SPAN> void* <SPAN lang=zh-cn>赋值给</SPAN> int 
      *<SPAN lang=zh-cn> 类型变量”。所以必须通过</SPAN> <B>(int *)<SPAN lang=zh-cn> 
      </SPAN></B><SPAN lang=zh-cn>来将强制转换。</SPAN></P>
      <P><SPAN lang=zh-cn>第二、函数的实参为 </SPAN>sizeof(int) <SPAN 
      lang=zh-cn>,用于指明一个整型数据需要的大小。如果你写成:</SPAN></P>
      <P> </P>
      <P>int* p = (int *) malloc (1);</P>
      <P><SPAN 
      lang=zh-cn>代码也能通过编译,但事实上只分配了1个字节大小的内存空间,当你往里头存入一个整数,就会有3个字节无家可归,而直接“住进邻居家”!造成的结果是后面的内存中原有数据内容全部被清空。</SPAN></P>
      <P> </P>
      <P>malloc <SPAN lang=zh-cn>也可以达到</SPAN> new [] <SPAN 
      lang=zh-cn>的效果,申请出一段连续的内存,方法无非是指定你所需要内存大小。</SPAN></P>
      <P> </P>
      <P><SPAN lang=zh-cn>比如想分配100个</SPAN>int<SPAN lang=zh-cn>类型的空间:</SPAN></P>
      <P> </P>
      <P>int* p = (int *) malloc ( sizeof(int) * 100 ); //<SPAN 
      lang=zh-cn>分配可以放得下100个整数的内存空间。</SPAN></P>
      <P> </P>
      <P><SPAN lang=zh-cn>另外有一点不能直接看出的区别是,</SPAN>malloc <SPAN 
      lang=zh-cn>只管分配内存,并不能对所得的内存进行初始化,所以得到的一片新内存中,其值将是随机的。</SPAN></P>
      <P> </P>
      <P><SPAN lang=zh-cn>除了分配及最后释放的方法不一样以外,通过</SPAN>malloc<SPAN 
      lang=zh-cn>或new得到指针,在其它操作上保持一致。</SPAN></P>
      <P> </P>
      <H4><B><A name=20.5.2>20.5.2</A> <SPAN lang=zh-cn>释放内存 </SPAN>free<SPAN 
      lang=zh-cn> 函数</SPAN></B></H4>
      <P> </P>
      <P><SPAN lang=zh-cn>需要包含头文件</SPAN>(<SPAN lang=zh-cn>和</SPAN> malloc <SPAN 
      lang=zh-cn>一样</SPAN>)<SPAN lang=zh-cn>:</SPAN></P>
      <P>#include &lt;alloc.h&gt;</P>
      <P><SPAN lang=zh-cn>或</SPAN></P>
      <P>#include &lt;stdlib.h&gt;</P>
      <P> </P>
      <P><SPAN lang=zh-cn>函数声明:</SPAN></P>
      <P><SPAN lang=zh-cn>void free(void *block);</SPAN></P>
      <P> </P>
      <P><SPAN lang=zh-cn>即:</SPAN> void free(<SPAN lang=zh-cn>指针变量</SPAN>)<SPAN 
      lang=zh-cn>;</SPAN></P>
      <P><SPAN lang=zh-cn>之所以把形参中的指针声明为</SPAN> void* <SPAN 
      lang=zh-cn>,是因为</SPAN>free<SPAN 
      lang=zh-cn>必须可以释放任意类型的指针,而任意类型的指针都可以转换为</SPAN>void *<SPAN 
      lang=zh-cn>。</SPAN></P>
      <P> </P>
      <P><SPAN lang=zh-cn>举例:</SPAN></P>
      <P> </P>
      <P>int* p = (int *) malloc(4);&nbsp; </P>
      <P> </P>
      <P>*p = 100;</P>
      <P> </P>
      <P>free(p); //<SPAN lang=zh-cn>释放</SPAN> p <SPAN 
      lang=zh-cn>所指的内存空间</SPAN></P>
      <P> </P>
      <P><SPAN lang=zh-cn>或者:</SPAN></P>
      <P> </P>
      <P>int* p = (int *) malloc ( sizeof(int) * 100 ); //<SPAN 
      lang=zh-cn>分配可以放得下100个整数的内存空间。</SPAN></P>
      <P> </P>
      <P><SPAN lang=zh-cn>……</SPAN></P>
      <P> </P>
      <P>free(p);</P>
      <P> </P>
      <P>free <SPAN lang=zh-cn>不管你的指针指向多大的空间</SPAN>,<SPAN 
      lang=zh-cn>均可以正确地进行释放,这一点释放比</SPAN> delete/delete [] <SPAN 
      lang=zh-cn>要方便。不过,必须注意,如果你在分配指针时,用的是</SPAN>new<SPAN 
      lang=zh-cn>或</SPAN>new[]<SPAN 
      lang=zh-cn>,那么抱歉,当你在释放内存时,你并不能图方便而使用</SPAN>free<SPAN 
      lang=zh-cn>来释放。反过来,你用</SPAN>malloc <SPAN 
      lang=zh-cn>分配的内存,也不能用</SPAN>delete<SPAN lang=zh-cn>/de</SPAN>lete[] <SPAN 
      lang=zh-cn>来释放。一句话,</SPAN>new/delete<SPAN 
      lang=zh-cn>、</SPAN>new[]/delete[]<SPAN lang=zh-cn>、</SPAN>malloc/free<SPAN 
      lang=zh-cn> 三对均需配套使用,不可混用!</SPAN></P>
      <P> </P>
      <P>int* p = new int[100];</P>
      <P>... ...</P>
      <P>free(p);&nbsp; //ERROR!<SPAN lang=zh-cn> p 是由</SPAN>new <SPAN 
      lang=zh-cn>所得。</SPAN></P>
      <P> </P>
      <P><SPAN lang=zh-cn>这也是我们必须学习 </SPAN>malloc <SPAN lang=zh-cn>与</SPAN> free 
      <SPAN lang=zh-cn>的重要理由之一,有时候,我们调用操作系统的函数(</SPAN>Windows <SPAN 
      lang=zh-cn>API)时,会遇到由我们的程序来分配内存,API函数来释放内存;或API函数来分配内存,而我们的程序来负责释放,这时,必须用</SPAN>malloc<SPAN 
      lang=zh-cn>或</SPAN>free<SPAN lang=zh-cn>来进行相应的工作。</SPAN></P>
      <P> </P>
      <P><SPAN lang=zh-cn>当然,保证所说的内存分配与释放方式不匹配的错误发生,</SPAN>Windows API<SPAN 
      lang=zh-cn>函数也提供了一套专门的内存管理函数给程序员</SPAN>,<SPAN 
      lang=zh-cn>为了不在这一章里放太多相混的内容,我们在</SPAN>Windows<SPAN 
      lang=zh-cn>编程的课程再讲相关内容。</SPAN></P>
      <P> </P>
      <P><SPAN lang=zh-cn>最后还有一个函数,也是我们要学习C方式的内存管理函数的原因。</SPAN></P>
      <P> </P>
      <H4><B><A name=20.5.3>20.5.3</A> <SPAN lang=zh-cn>重</SPAN>调空间的<SPAN 
      lang=zh-cn>大小</SPAN>: <SPAN lang=en-us>realloc </SPAN>函数</B></H4>
      <P> </P>
      <P><SPAN lang=zh-cn>需要包含头文件</SPAN>(<SPAN lang=zh-cn>和</SPAN> malloc <SPAN 
      lang=zh-cn>一样</SPAN>)<SPAN lang=zh-cn>:</SPAN></P>
      <P>#include &lt;alloc.h&gt;</P>
      <P><SPAN lang=zh-cn>或</SPAN></P>
      <P>#include &lt;stdlib.h&gt;</P>
      <P> </P>
      <P><SPAN lang=zh-cn>函数声明:</SPAN></P>
      <P>void *realloc(void *block, <SPAN lang=en-us>int</SPAN> size);</P>
      <P> </P>
      <P><SPAN lang=en-us>block </SPAN>是指向要扩张或缩小的内存空间的指针。<SPAN 
      lang=en-us>size</SPAN> 指定新的大小。</P>
      <P> </P>
      <P><SPAN lang=en-us>realloc </SPAN>可以对给定的指针所指的空间进行扩大或者缩小。<SPAN 
      lang=en-us>size </SPAN>是新的目标大小。比如,原来空间大小是40个字节,现在可以将<SPAN lang=en-us>size 
      </SPAN>指定为60,这样就扩张了20个字节;或者,将<SPAN lang=en-us>size 
      </SPAN>指定为20,则等于将空间缩小了20个字节。</P>
      <P> </P>
      <P>无论是扩张或是缩小,原有内存的中内容将保持不变。当然,对于缩小,则被缩小的那一部分的内容会丢失。</P>
      <P> </P>
      <P>举例:</P>
      <P> </P>
      <P><SPAN lang=en-us>/</SPAN>/先用<SPAN lang=en-us> malloc </SPAN>分配一指针</P>
      <P><SPAN lang=en-us>int* p = (int *) malloc (sizeof(int) * 10);&nbsp; 
      //</SPAN>可以存放10个整数</P>
      <P> </P>
      <P>……</P>
      <P><SPAN lang=en-us>//</SPAN>现在,由于些某原因,我们需要向p所指的空间中存放15个整数</P>
      <P>//原来的空间不够了:</P>
      <P><SPAN lang=en-us>p = (int *) realloc (p, sizeof(int) *15); 
      //</SPAN>空间扩张了<SPAN lang=en-us> (15 - 10) * sizeof(int) = 20 
</SPAN>个字节</P>
      <P> </P>
      <P>……</P>
      <P> </P>
      <P><SPAN lang=en-us>//</SPAN>接下来,我们决定将p所指内存空间紧缩为5个整数的大小:</P>
      <P><SPAN lang=en-us>p = (int *) realloc (p, sizeof(int) * 5); 
      //</SPAN>缩小了<SPAN lang=en-us> (15 - 5) * sizeof(int) = 40 </SPAN>个字节</P>
      <P> </P>
      <P>……</P>
      <P> </P>
      <P><SPAN lang=en-us>free (p);</SPAN></P>
      <P> </P>
      <P>这么看起来,<SPAN lang=en-us>realloc 
      </SPAN>有点像是施工队对一个已建的房屋进行改修:可以将房间后面再扩建几间,也可以拆掉几间。不管是扩还是拆,屋里原来的东西并不改变。</P>
      <P>不过,这里要特别提醒一点:这个施工队有时会做这种事:1、在一块新的空地上新建一座指定大小的房屋;2、接着,将原来屋子里的东西原样照搬到新屋;3、拆掉原来的屋子。</P>
      <P>这是什么指意呢?</P>
      <P><B><SPAN lang=en-us>realloc 
      </SPAN>并不保证调整后的内存空间和原来的内存空间保持同一内存地址。相反,<SPAN lang=en-us>realloc 
      </SPAN>返回的指针很可能指向一个新的地址。</B></P>
      <P>所以,在代码中,我们必须将<SPAN lang=en-us>realloc</SPAN>返回的值,重新赋值给<SPAN lang=en-us> 
      p :</SPAN></P>
      <P> </P>
      <P><SPAN lang=en-us>p = (int *) realloc (p, sizeof(int) *15);</SPAN></P>
      <P> </P>
      <P> </P>
      <P>甚至,你可以传一个空指针(0)给<SPAN lang=en-us> realloc </SPAN>,则此时<SPAN 
      lang=en-us>realloc </SPAN>作用完全相当于<SPAN lang=en-us>malloc</SPAN>。</P>
      <P> </P>
      <P><SPAN lang=en-us>int* p = (int *) realloc (<B>0</B>,sizeof(int) * 
      10);&nbsp; //</SPAN>分配一个全新的内存空间,</P>
      <P> </P>
      <P>这一行,作用完全等同于:</P>
      <P> </P>
      <P><SPAN lang=en-us>int* p = (int *) malloc(sizeof(int) * 10); </SPAN></P>
      <P> </P>
      <H4><B><SPAN lang=zh-cn><A name=20.5.4>20.5.4</A> </SPAN><SPAN 
      lang=en-us>malloc</SPAN>、<SPAN lang=en-us>realloc</SPAN>、<SPAN 
      lang=en-us>free</SPAN>的例子</B></H4>
      <P> </P>
      <P>打开CB6,新建一空白控制台工程。</P>
      <P> </P>
      <P>第一步:在<SPAN lang=en-us> Unit1.cpp </SPAN>中的最前面,加入引用<SPAN lang=en-us> 
      alloc.h</SPAN> 等头文件的代码:</P>
      <P> </P>
      <P>……</P>
      <P>#pragma hdrstop</P>
      <P><B>#include &lt;alloc.h&gt;<SPAN lang=en-us> 
      //</SPAN>三个函数的声明都这个头文件里</B></P>
      <P><B><SPAN lang=en-us>#include &lt;iostream.h&gt; </SPAN></B></P>
      <P>……</P>
      <P> </P>
      <P>第二步:将以下代码加入主函数<SPAN lang=en-us> main</SPAN> 中间:</P>
      <P> </P>
      <P>int* p = (int *) malloc (sizeof(int) * 10);</P>
      <P> </P>
      <P>cout &lt;&lt; "realloc 之前p指向的内存地址: " &lt;&lt; p &lt;&lt; endl;</P>
      <P> </P>
      <P>for (int i=0; i&lt;10; i++)</P>
      <P>{</P>
      <P><SPAN lang=en-us>&nbsp;&nbsp; </SPAN>p[i] = i + 1;</P>
      <P>}</P>
      <P> </P>
      <P>cout &lt;&lt; "realloc 之前p指向的内存中的内容:" &lt;&lt; endl;</P>
      <P> </P>
      <P>for (int i=0; i&lt;10; i++)</P>
      <P>{</P>
      <P><SPAN lang=en-us>&nbsp;&nbsp; </SPAN>cout &lt;&lt; p[i] &lt;&lt; 
      ",";</P>
      <P><SPAN lang=en-us>}</SPAN></P>
      <P>cout &lt;&lt; endl;</P>
      <P> </P>
      <P>p = (int *) realloc (p, sizeof(int) * 15);</P>
      <P> </P>
      <P>cout &lt;&lt; "realloc 之后p指向的内存地址: " &lt;&lt; p &lt;&lt; endl; 
      <P>
      <P>  
      <P>cout &lt;&lt; "realloc 之后p指向的内存中的内容:" &lt;&lt; endl; 
      <P>
      <P>for (int i=0; i&lt;15; i++) 
      <P>{ 
      <P>&nbsp;&nbsp; cout &lt;&lt; p[i] &lt;&lt; ","; 
      <P>} 
      <P>cout &lt;&lt; endl; 
      <P>  
      <P>
      <P>free (p); 
      <P>
      <P>
      <P>system("PAUSE"); 
      <P> </P>
      <P> </P>
      <P>运行结果:</P>
      <P align=center><IMG height=118 
      src="第20章 指针二 为指针分配和释放空间.files/ls20.h12.gif" width=396 border=0></P>
      <P align=center><SPAN lang=en-us>(malloc, realloc, free </SPAN>上机<SPAN 
      lang=zh-cn>题</SPAN><SPAN lang=en-us>)</SPAN></P>
      <P> </P>
      <P><SPAN lang=zh-cn>从图中我们看到 </SPAN>realloc<SPAN lang=zh-cn> 
      前后的p指向的内存地址同样是</SPAN> 9647936 <SPAN 
      lang=zh-cn>。但记住,这并不是结论,真正的结论我们已经说过“</SPAN>realloc <SPAN 
      lang=zh-cn><B>并不保证</B>返回和原来一样的地址。”所谓的“并不保证”的意思是:“我尽力去做了,但仍然有可能做不到。”。</SPAN></P>
      <P> </P>
      <P><SPAN lang=zh-cn>无论调用几次</SPAN> realloc,<SPAN lang=zh-cn>最后我们只需一次</SPAN> 
      free<SPAN lang=zh-cn>。</SPAN></P></TD></TR>
  <TR>
    <TD 
    style="FONT-SIZE: 10pt; TEXT-INDENT: 20px; LINE-HEIGHT: 150%; FONT-FAMILY: &Euml;&Icirc;&Igrave;&aring;" 
    width="100%" height=37> </TD></TR></TBODY></TABLE></CENTER></BODY></HTML>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -