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

📄 effective c++ 2e item8.htm

📁 Effective-c++.国外很经典的一本关于c++编程的电子书。
💻 HTM
📖 第 1 页 / 共 2 页
字号:
<P>&nbsp;&nbsp;&nbsp; if (分配成功)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return 
(指向内存的指针);</P>
<P>&nbsp;&nbsp;&nbsp; // 分配不成功,找出当前出错处理函数<BR>&nbsp;&nbsp;&nbsp; new_handler 
globalHandler = set_new_handler(0);<BR>&nbsp;&nbsp;&nbsp; 
set_new_handler(globalHandler);</P>
<P>&nbsp;&nbsp;&nbsp; if (globalHandler) 
(*globalHandler)();<BR>&nbsp;&nbsp;&nbsp; else throw std::bad_alloc();<BR>&nbsp; 
}<BR>}</P>
<P>处理零字节请求的技巧在于把它作为请求一个字节来处理。这看起来也很怪,但简单,合法,有效。而且,你又会多久遇到一次零字节请求的情况呢?</P>
<P>你又会奇怪上面的伪代码中为什么把出错处理函数置为0后又立即恢复。这是因为没有办法可以直接得到出错处理函数的指针,所以必须通过调用set_new_handler来找到。办法很笨但也有效。</P>
<P>条款7提到operator new内部包含一个无限循环,上面的代码清楚地说明了这一点——while 
(1)将导致无限循环。跳出循环的唯一办法是内存分配成功或出错处理函数完成了条款7所描述的事件中的一种:得到了更多的可用内存;安装了一个新的new-handler(出错处理函数);卸除了new-handler;抛出了一个std::bad_alloc或其派生类型的异常;或者返回失败。现在明白了为什么new-handler必须做这些工作中的一件。如果不做,operator 
new里面的循环就不会结束。</P>
<P>很多人没有认识到的一点是operator 
new经常会被子类继承。这会导致某些复杂性。上面的伪代码中,函数会去分配size字节的内存(除非size为0)。size很重要,因为它是传递给函数的参数。但是大多数针对类所写的operator 
new(包括条款10中的那种)都是只为特定的类设计的,不是为所有的类,也不是为它所有的子类设计的。这意味着,对于一个类X的operator 
new来说,函数内部的行为在涉及到对象的大小时,都是精确的sizeof(X):不会大也不会小。但由于存在继承,基类中的operator 
new可能会被调用去为一个子类对象分配内存:<BR>class Base {<BR>public:<BR>&nbsp; static void * 
operator new(size_t size);<BR>&nbsp; ...<BR>};</P>
<P>class Derived: public Base&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 
Derived类没有声明operator new<BR>{ ... 
};&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
// </P>
<P>Derived *p = new Derived;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 
调用Base::operator new</P>
<P>如果Base类的operator 
new不想费功夫专门去处理这种情况——这种情况出现的可能性不大——那最简单的办法是把这个“错误”数量的内存分配请求转给标准operator 
new来处理,象下面这样:<BR>void * Base::operator new(size_t size)<BR>{<BR>&nbsp; if (size 
!= 
sizeof(Base))&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
// 如果数量“错误”,让标准operator new<BR>&nbsp;&nbsp;&nbsp; return ::operator 
new(size);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 
去处理这个请求<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
// </P>
<P>&nbsp; 
...&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
// 否则处理这个请求<BR>}</P>
<P>“停!”我听见你在叫,“你忘了检查一种虽然不合理但是有可能出现的一种情况——size有可能为零!”是的,我没检查,但拜托下次再叫出声的时候不要这么文绉绉的。:)但实际上检查还是做了,只不过融合到size 
!= 
sizeof(Base)语句中了。C++标准很怪异,其中之一就是规定所以独立的(freestanding)类的大小都是非零值。所以sizeof(Base)永远不可能是零(即使base类没有成员),如果size为零,请求会转到::operator 
new,由它来以一种合理的方式对请求进行处理。(有趣的是,如果Base不是独立的类,sizeof(Base)有可能是零,详细说明参见"my article on 
counting objects")。</P>
<P>如果想控制基于类的数组的内存分配,必须实现operator new的数组形式——operator 
new[](这个函数常被称为“数组new”,因为想不出"operator new[]")该怎么发音)。写operator 
new[]时,要记住你面对的是“原始”内存,不能对数组里还不存在的对象进行任何操作。实际上,你甚至还不知道数组里有多少个对象,因为不知道每个对象有多大。基类的operator 
new[]会通过继承的方式被用来为子类对象的数组分配内存,而子类对象往往比基类要大。所以,不能想当然认为Base::operator 
new[]里的每个对象的大小都是sizeof(Base),也就是说,数组里对象的数量不一定就是(请求字节数)/sizeof(Base)。关于operator 
new[]的详细介绍参见条款M8。</P>
<P>重写operator new(和operator new[])时所有要遵循的常规就这些。对于operator delete(以及它的伙伴operator 
delete[]),情况更简单。所要记住的只是,C++保证删除空指针永远是安全的,所以你要充分地应用这一保证。下面是非类成员形式的operator 
delete的伪代码:<BR>void operator delete(void *rawMemory)<BR>{<BR>&nbsp; if 
(rawMemory == 0) return;&nbsp;&nbsp;&nbsp; <A 
href="file://如/">file://如/</A>果指针为空,返回<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
// </P>
<P>&nbsp; 释放rawMemory指向的内存;</P>
<P>&nbsp; return;<BR>}</P>
<P>这个函数的类成员版本也简单,只是还必须检查被删除的对象的大小。假设类的operator new将“错误”大小的分配请求转给::operator 
new,那么也必须将“错误”大小的删除请求转给::operator delete:</P>
<P>class Base 
{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
// 
和前面一样,只是这里声明了<BR>public:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
// operator delete<BR>&nbsp; static void * operator new(size_t size);<BR>&nbsp; 
static void operator delete(void *rawMemory, size_t size);<BR>&nbsp; 
...<BR>};</P>
<P>void Base::operator delete(void *rawMemory, size_t size)<BR>{<BR>&nbsp; if 
(rawMemory == 0) return;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 检查空指针</P>
<P>&nbsp; if (size != sizeof(Base)) {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 
如果size"错误",<BR>&nbsp;&nbsp;&nbsp; ::operator delete(rawMemory);&nbsp; // 
让标准operator来处理请求<BR>&nbsp;&nbsp;&nbsp; 
return;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
<BR>&nbsp; }</P>
<P>&nbsp; 释放指向rawMemory的内存;</P>
<P>&nbsp; return;<BR>}</P>
<P>可见,有关operator new和operator 
delete(以及他们的数组形式)的规定不是那么麻烦,重要的是必须遵守它。只要内存分配程序支持new-handler函数并正确地处理了零内存请求,就差不多了;如果内存释放程序又处理了空指针,那就没其他什么要做的了。至于在类成员版本的函数里增加继承支持,那将很快就可以完成。<BR></P><BR><BR></DIV></DIV></DIV><BR><BR>
<SCRIPT src="Effective C++ 2e Item8.files/get_readnum.htm"></SCRIPT>

<TABLE cellSpacing=1 cellPadding=2 width=770 align=center bgColor=#666666 
border=0>
  <TBODY>
  <TR>
    <TH id=white bgColor=#990000><FONT 
  color=#ffffff>对该文的评论</FONT></TH></TR></TBODY></TABLE><BR>
<SCRIPT language=javascript>
<!--
function isEmpty(s)
{  
	return ((s == null) || (s.length == 0))
}
function submit1()
{
   if (isEmpty(document.add_critique.csdnname.value) || isEmpty(document.add_critique.csdnpassword.value) || isEmpty(document.add_critique.critique_content.value))
   {
      alert('登陆名,密码,评论不能为空!!!!')   ;
      return false;
   }
   document.add_critique.submit();
 }
//-->
</SCRIPT>

<TABLE cellSpacing=1 cellPadding=2 width=770 align=center bgColor=#666666 
border=0>
  <TBODY>
  <TR>
    <TH id=white bgColor=#990000><FONT 
color=#ffffff>发表评论</FONT></TH></TR></TBODY></TABLE>
<TABLE cellSpacing=1 cellPadding=2 width=770 align=center bgColor=#ffffff 
border=0>
  <TBODY>
  <TR>
    <TD>
      <FORM name=add_critique action=/develop/add_critique.asp 
      method=post><INPUT type=hidden value=add name=critique_add> <INPUT 
      type=hidden value=8614 name=from> &nbsp;&nbsp;评论人: <INPUT name=csdnname> 
      &nbsp;&nbsp;密码: <INPUT type=password name=csdnpassword> 
      &nbsp;&nbsp;评论:<BR>&nbsp;&nbsp; <TEXTAREA name=critique_content rows=8 cols=100></TEXTAREA><BR>&nbsp;&nbsp; 
<INPUT onclick=javascript:submit1(); type=button value=发表评论 name=ubmit> 
      <INPUT type=hidden value=8614 name=id> </FORM></TD></TR></TBODY></TABLE>
<TABLE width=770 border=0>
  <TBODY>
  <TR>
    <TD>
      <TABLE cellPadding=2 width=770 border=0>
        <TBODY>
        <TR>
          <TD height=10></TD></TR>
        <TR>
          <TD align=left width=130><!--Adforward Begin:--><IFRAME 
            marginWidth=0 marginHeight=0 
            src="Effective C++ 2e Item8.files/adfshow.htm" frameBorder=0 
            width=120 scrolling=no 
            height=60>
<SCRIPT LANGUAGE="JavaScript1.1" SRC="http://ok100.allyes.com/main/adfshow?user=CP_CSDNButton|CG_Button|C_BottomButton&db=ok100&local=yes&js=on">
</SCRIPT>
<NOSCRIPT>
<A HREF=http://ok100.allyes.com/main/adfclick?user=CP_CSDNButton|CG_Button|C_BottomButton&db=ok100>
<IMG SRC=http://ok100.allyes.com/main/adfshow?user=CP_CSDNButton|CG_Button|C_BottomButton&db=ok100 WIDTH=120 HEIGHT=60 BORDER=0></a>
</NOSCRIPT>
</IFRAME><!--Adforward End--></TD>
          <TD align=middle width=510>
            <OBJECT id=Movie1 
            codeBase=http://active.macromedia.com/flash2/cabs/swflash.cab#version=4,0,0,0 
            height=60 width=468 
            classid=clsid:D27CDB6E-AE6D-11cf-96B8-444553540000><PARAM NAME="movie" VALUE="http://www.csdn.net/images/ad/csdn_media.swf"><PARAM NAME="quality" VALUE="high">
               <EMBED src="http://www.csdn.net/images/ad/csdn_media.swf" 
            quality=high WIDTH=468 HEIGHT=60 
            TYPE="application/x-shockwave-flash" 
            PLUGINSPAGE="http://www.macromedia.com/shockwave/download/index.cgi?P1_Prod_Version=ShockwaveFlash"> 
            </EMBED> </OBJECT></TD>
          <TD align=middle width=130><A 
            href="http://www.hd315.gov.cn/beian/view.asp?bianhao=010202001032100010"><IMG 
            src="http://www.csdn.net/images/biaoshi.gif" border=0></A> 
        </TD></TR></TBODY></TABLE></TD></TR>
  <TR>
    <TD>
      <TABLE height=20 cellSpacing=0 cellPadding=0 width=770 align=default 
      bgColor=#1f60a0 border=0>
        <TBODY>
        <TR class=font13px vAlign=center align=middle>
          <TD class=font13px vAlign=center width=90 height=2></TD>
          <TD width=2 rowSpan=2><IMG height=13 
            src="http://www.csdn.net/images/ad4.gif" width=2></TD>
          <TD class=font13px width=90 height=2></TD>
          <TD width=3 rowSpan=2><FONT color=#ffffff><IMG height=13 
            src="http://www.csdn.net/images/ad4.gif" width=2></FONT></TD>
          <TD class=font13px width=90 height=2></TD>
          <TD width=2 rowSpan=2><IMG height=13 
            src="http://www.csdn.net/images/ad4.gif" width=2></TD>
          <TD class=font13px width=90 height=2></TD>
          <TD width=3 rowSpan=2><FONT color=#ffffff><IMG height=13 
            src="http://www.csdn.net/images/ad4.gif" width=2></FONT></TD>
          <TD width=350 height=2><FONT color=#ffffff></FONT></TD>
          <TD width=10 rowSpan=2><FONT color=#ffffff><IMG height=11 
            src="http://www.csdn.net/images/ad3.gif" width=6></FONT></TD>
          <TD class=font13px width=60 height=2></TD></TR>
        <TR class=font14px vAlign=center align=middle>
          <TD class=font13px vAlign=center width=90><A 
            href="http://www.csdn.net/intro/intro.shtm"><FONT 
            color=#ffffff>美达美简介</FONT></A></TD>
          <TD class=font13px width=90><A 
            href="http://www.csdn.net/intro/ad.shtm"><FONT 
            color=#ffffff>广告服务</FONT></A></TD>
          <TD class=font13px width=90><A 
            href="http://www.csdn.net/English/"><FONT 
            color=#ffffff>英语步步高</FONT></A></TD>
          <TD class=font13px width=90><A href="http://www.csdn.net/dev/"><FONT 
            color=#ffffff>程序员大本营</FONT></A></TD>
          <TD align=right width=350><SPAN class=font13px><A 
            href="mailto:webmaster@csdn.net"><FONT 
            color=#ffffff>百联美达美科技有限公司</FONT></A></SPAN><FONT color=#ffffff><SPAN 
            class=font13px> </SPAN></FONT></TD>
          <TD class=font13px width=60><FONT color=#ffffff>版权所有</FONT>
            <SCRIPT>document.write("<img src=http://202.106.156.10/stat.asp?user=designol&refer="+escape(document.referrer)+"&cur="+escape(document.URL)+" width=0 height=0 border=0>");</SCRIPT>
          </TD></TR></TBODY></TABLE></TD></TR></TBODY></TABLE></CENTER></BODY></HTML>

⌨️ 快捷键说明

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