📄 ec2.htm
字号:
</UL><A NAME="13640"></A>
<P><A NAME="dingp79"></A>
The conventions, then, for <CODE>operator</CODE> <CODE>new</CODE> and <CODE>operator</CODE> <CODE>delete</CODE> (and their array counterparts) are not particularly onerous, but it is important that you obey them. If your allocation routines support new-handler functions and correctly deal with zero-sized requests, you're all but finished, and if your deallocation routines cope with null pointers, there's little more to do. Add support for inheritance in member versions of the functions, and <I>presto!</I> — you're <NOBR>done.<SCRIPT>create_link(79);</SCRIPT>
</NOBR></P>
<!-- SectionName="E9: Avoid hiding the 'normal' form of new" -->
<A NAME="1961"></A><DIV ALIGN="CENTER"><FONT SIZE="-1">Back to <A HREF="#120851">Item 8: Adhere to convention when writing operator new and operator delete.</A>
<BR>Continue to <A HREF="#1986">Item 10: Write operator delete if you write operator new.</A></FONT></DIV>
<P><A NAME="dingp80"></A><FONT ID="eititle">Item 9: Avoid hiding the "normal" form of <CODE>new</CODE>.</FONT><SCRIPT>create_link(80);</SCRIPT>
</P>
<A NAME="1962"></A>
<P><A NAME="dingp81"></A>
A declaration of a name in an inner scope hides the same name in outer scopes, so for a function <CODE>f</CODE> at both global and class scope, the member function will hide the global <NOBR>function:<SCRIPT>create_link(81);</SCRIPT>
</NOBR></P>
<A NAME="61573"></A>
<UL><PRE><A NAME="p38"></A>
void f(); // global function
</PRE>
</UL><A NAME="61574"></A>
<UL><PRE>class X {
public:
void f(); // member function
};
</PRE>
</UL><A NAME="1965"></A>
<UL><PRE>X x;
</PRE>
</UL><A NAME="1966"></A>
<UL><PRE>
f(); // calls global f
</PRE>
</UL><A NAME="1967"></A>
<UL><PRE>
x.f(); // calls X::f
</PRE>
</UL><A NAME="1968"></A>
<P><A NAME="dingp82"></A>
This is unsurprising and normally causes no confusion, because global and member functions are usually invoked using different syntactic forms. However, if you add to this class an <CODE>operator</CODE> <CODE>new</CODE> taking additional parameters, the result is likely to be an <NOBR>eye-opener:<SCRIPT>create_link(82);</SCRIPT>
</NOBR></P>
<A NAME="1970"></A>
<UL><PRE>class X {
public:
void f();
</PRE>
</UL><A NAME="1971"></A>
<UL><PRE> // operator new allowing specification of a
// new-handling function
static void * operator new(size_t size, new_handler p);
};
</PRE>
</UL><A NAME="1972"></A>
<UL><PRE>
void specialErrorHandler(); // definition is elsewhere
</PRE>
</UL><A NAME="1973"></A>
<UL><PRE>X *px1 =
new (specialErrorHandler) X; // calls X::operator new
</PRE>
</UL><A NAME="1974"></A>
<UL><PRE>
X *px2 = new X; // error!
</PRE>
</UL><A NAME="1975"></A>
<P><A NAME="dingp83"></A>
By declaring a function called "operator new" inside the class, you inadvertently block access to the "normal" form of <CODE>new</CODE>. Why this is so is discussed in <A HREF="./EC7_FR.HTM#8569" TARGET="_top">Item 50</A>. Here we're more interested in figuring out how to avoid the <NOBR>problem.<SCRIPT>create_link(83);</SCRIPT>
</NOBR></P>
<A NAME="1979"></A>
<P><A NAME="dingp84"></A>
One solution is to write a class-specific <CODE>operator</CODE> <CODE>new</CODE> that supports the "normal" invocation form. If it does the same thing as the global version, that can be efficiently and elegantly encapsulated as an inline <NOBR>function:<SCRIPT>create_link(84);</SCRIPT>
</NOBR></P>
<A NAME="1980"></A>
<UL><PRE>class X {
public:
void f();
</PRE>
</UL><A NAME="1981"></A>
<UL><PRE> static void * operator new(size_t size, new_handler p);
</PRE>
</UL><A NAME="1982"></A>
<UL><PRE> static void * operator new(size_t size)
{ return ::operator new(size); }
};
</PRE>
</UL><A NAME="1983"></A>
<UL><PRE><A NAME="p39"></A>X *px1 =
new (specialErrorHandler) X; // calls X::operator
// new(size_t, new_handler)
</PRE>
</UL><A NAME="1984"></A>
<UL><PRE>
X* px2 = new X; // calls X::operator
// new(size_t)
</PRE>
</UL><A NAME="13809"></A>
<P><A NAME="dingp85"></A>
An alternative is to provide a default parameter value (see <A HREF="./EC4_FR.HTM#6250" TARGET="_top">Item 24</A>) for each additional parameter you add to <CODE>operator</CODE> <CODE>new</CODE>:<SCRIPT>create_link(85);</SCRIPT>
</P>
<A NAME="13819"></A>
<UL><PRE>class X {
public:
void f();
</PRE>
</UL><A NAME="13820"></A>
<UL><PRE> static
void * operator new(size_t size, // note default
new_handler p = 0); // value for p
};
</PRE>
</UL><A NAME="13822"></A>
<UL><PRE>
X *px1 = new (specialErrorHandler) X; // fine
</PRE>
</UL><A NAME="13836"></A>
<UL><PRE>X* px2 = new X; // also fine
</PRE>
</UL><A NAME="1985"></A>
<P><A NAME="dingp86"></A>
Either way, if you later decide to customize the behavior of the "normal" form of <CODE>new</CODE>, all you need to do is rewrite the function; callers will get the customized behavior automatically when they <NOBR>relink.<SCRIPT>create_link(86);</SCRIPT>
</NOBR></P>
<!-- SectionName="E10: Write delete if you write new" -->
<A NAME="1987"></A><A NAME="1986"></A><DIV ALIGN="CENTER"><FONT SIZE="-1">Back to <A HREF="#1961">Item 9: Avoid hiding the "normal" form of new.</A>
<BR>Continue to <A HREF="./EC3.HTM" TARGET="_top">Constructors, Destructors, and Assignment Operators</A></FONT></DIV>
<P><A NAME="dingp87"></A><FONT ID="eititle">Item 10: Write <CODE>operator</CODE> <CODE>delete</CODE> if you write <CODE>operator</CODE> <CODE>new</CODE>.</FONT><SCRIPT>create_link(87);</SCRIPT>
</P>
<p><A NAME="dingp88"></A>
Let's step back for a moment and return to fundamentals. Why would anybody want to write their own version of <CODE>operator</CODE> <CODE>new</CODE> or <CODE>operator</CODE> <CODE>delete</CODE> in the first <NOBR>place?<SCRIPT>create_link(88);</SCRIPT>
</NOBR></P>
<A NAME="1988"></A>
<P><A NAME="dingp89"></A>
More often than not, the answer is efficiency. The default versions of <CODE>operator</CODE> <CODE>new</CODE> and <CODE>operator</CODE> <CODE>delete</CODE> are perfectly adequate for general-purpose use, but their flexibility inevitably leaves room for improvements in their performance in a more circumscribed context. This is especially true for applications that dynamically allocate a large number of small <NOBR>objects.<SCRIPT>create_link(89);</SCRIPT>
</NOBR></P>
<A NAME="1989"></A>
<P><A NAME="dingp90"></A>
As an example, consider a class for representing airplanes, where the <CODE>Airplane</CODE> class contains only a pointer to the actual representation for airplane objects (a technique discussed in <A HREF="./EC5_FR.HTM#6793" TARGET="_top">Item 34</A>):<SCRIPT>create_link(90);</SCRIPT>
</P>
<A NAME="28421"></A>
<UL><PRE>class AirplaneRep { ... }; // representation for an
// Airplane object
class Airplane {
public:
...
private:
AirplaneRep *rep; // pointer to representation
};
</PRE>
</UL><A NAME="1994"></A>
<P><A NAME="dingp91"></A>
<A NAME="p40"></A>An <CODE>Airplane</CODE> object is not very big; it contains but a single pointer. (As explained in Items <A HREF="./EC3_FR.HTM#223029" TARGET="_top">14</A> and <A HREF="../MEC/MC4_FR.HTM#41284" TARGET="_top">M24</A>, it may implicitly contain a second pointer if the <CODE>Airplane</CODE> class declares virtual functions.) When you allocate an <CODE>Airplane</CODE> object by calling <CODE>operator</CODE> <CODE>new</CODE>, however, you probably get back more memory than is needed to store this pointer (or pair of pointers). The reason for this seemingly wayward behavior has to do with the need for <CODE>operator</CODE> <CODE>new</CODE> and <CODE>operator</CODE> <CODE>delete</CODE> to communicate with one <NOBR>another.<SCRIPT>create_link(91);</SCRIPT>
</NOBR></P>
<A NAME="1995"></A>
<P><A NAME="dingp92"></A>
Because the default version of <CODE>operator</CODE> <CODE>new</CODE> is a general-purpose allocator, it must be prepared to allocate blocks of any size. Similarly, the default version of <CODE>operator</CODE> <CODE>delete</CODE> must be prepared to deallocate blocks of whatever size <CODE>operator</CODE> <CODE>new</CODE> allocated. For <CODE>operator</CODE> <CODE>delete</CODE> to know how much memory to deallocate, it must have some way of knowing how much memory <CODE>operator</CODE> <CODE>new</CODE> allocated in the first place. A common way for <CODE>operator</CODE> <CODE>new</CODE> to tell <CODE>operator</CODE> <CODE>delete</CODE> how much memory it allocated is by prepending to the memory it returns some additional data that specifies the size of the allocated block. That is, when you say <NOBR>this,<SCRIPT>create_link(92);</SCRIPT>
</NOBR></P>
<A NAME="1996"></A>
<UL><PRE>Airplane *pa = new Airplane;
</PRE>
</UL><A NAME="1997"></A>
<P><A NAME="dingp93"></A>you don't necessarily get back a block of memory that looks like <NOBR>this:<SCRIPT>create_link(93);</SCRIPT>
</NOBR></p>
<SPAN ID="Image1of1" STYLE="position: absolute; z-index:1; visibility: hidden"><IMG SRC="./IMAGES/GRAPHICS/DIAGRAMS/I_040A1.GIF" BORDER=0></SPAN>
<SPAN ID="Image1of2" STYLE="position: absolute; z-index:1; visibility: hidden"><IMG SRC="./IMAGES/GRAPHICS/DIAGRAMS/I_040A2.GIF" BORDER=0></SPAN>
<SPAN ID="Image1of3" STYLE="position: absolute; z-index:1; visibility: hidden"><IMG SRC="./IMAGES/GRAPHICS/DIAGRAMS/I_040A3.GIF" BORDER=0></SPAN>
<SPAN ID="Image1of4" STYLE="position: absolute; z-index:1; visibility: hidden"><IMG SRC="./IMAGES/GRAPHICS/DIAGRAMS/I_040A4.GIF" BORDER=0></SPAN>
<SPAN ID="Image1of5" STYLE="position: absolute; z-index:1; visibility: hidden"><IMG SRC="./IMAGES/GRAPHICS/DIAGRAMS/I_040A5.GIF" BORDER=0></SPAN>
<SPAN ID="Image1of6" STYLE="position: relative; z-index:1; visibility: hidden"><IMG SRC="./IMAGES/GRAPHICS/DIAGRAMS/I_040A5.GIF" BORDER=0></SPAN>
<A NAME="214466"></A>
<P><A NAME="dingp94"></A>Instead, you often get back a block of memory that looks more like <NOBR>this:<SCRIPT>create_link(94);</SCRIPT>
</NOBR></P>
<SPAN ID="Image2of1" STYLE="position: absolute; z-index:1; visibility: hidden"><IMG SRC="./IMAGES/GRAPHICS/DIAGRAMS/I_040B1.GIF" BORDER=0></SPAN>
<SPAN ID="Image2of2" STYLE="position: absolute; z-index:1; visibility: hidden"><IMG SRC="./IMAGES/GRAPHICS/DIAGRAMS/I_040B2.GIF" BORDER=0></SPAN>
<SPAN ID="Image2of3" STYLE="position: absolute; z-index:1; visibility: hidden"><IMG SRC="./IMAGES/GRAPHICS/DIAGRAMS/I_040B3.GIF" BORDER=0></SPAN>
<SPAN ID="Image2of4" STYLE="position: absolute; z-index:1; visibility: hidden"><IMG SRC="./IMAGES/GRAPHICS/DIAGRAMS/I_040B4.GIF" BORDER=0></SPAN>
<SPAN ID="Image2of5" STYLE="position: absolute; z-index:1; visibility: hidden"><IMG SRC="./IMAGES/GRAPHICS/DIAGRAMS/I_040B5.GIF" BORDER=0></SPAN>
<SPAN ID="Image2of6" STYLE="position: relative; z-index:1; visibility: hidden"><IMG SRC="./IMAGES/GRAPHICS/DIAGRAMS/I_040B5.GIF" BORDER=0
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -