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

📄 mi8.htm

📁 一个非常适合初学者入门的有关c++的文档
💻 HTM
📖 第 1 页 / 共 2 页
字号:

<A NAME="34292"></A>
<P><A NAME="dingp23"></A>
To avoid resource leaks, every dynamic allocation must be matched by an equal and opposite deallocation. The function <CODE>operator</CODE> <CODE>delete</CODE> is to the built-in <CODE>delete</CODE> operator as <CODE>operator</CODE> <CODE>new</CODE> is to the <CODE>new</CODE> operator. When you say something like this,
<A NAME="34296"></A><SCRIPT>create_link(23);</SCRIPT>
</P>
<UL><PRE>string *ps;
...
delete ps;                          // use the delete operator
</PRE>
</UL><A NAME="83299"></A><P><A NAME="dingp24"></A>
your compilers must generate code both to destruct the object <CODE>ps</CODE> points to and to deallocate the memory occupied by that <NOBR>object.<SCRIPT>create_link(24);</SCRIPT>
</NOBR></p><A NAME="74762"></A>
<P><A NAME="dingp25"></A>
The memory deallocation is performed by the <CODE>operator</CODE> <CODE>delete</CODE> function, which is usually declared like <NOBR>this:<SCRIPT>create_link(25);</SCRIPT>
</NOBR></p><A NAME="34304"></A>
<UL><PRE>void operator delete(void *memoryToBeDeallocated);
</PRE>
</UL><A NAME="34305"></A>
<P><A NAME="dingp26"></A>
<NOBR>Hence,<SCRIPT>create_link(26);</SCRIPT>
</NOBR></P>
<A NAME="34316"></A>
<UL><PRE>delete ps;
</PRE>
</UL><A NAME="34317"></A><P><A NAME="dingp27"></A>causes compilers to generate code that approximately corresponds to <NOBR>this:<SCRIPT>create_link(27);</SCRIPT>
</NOBR></P>
<A NAME="34318"></A>
<UL><PRE>
ps-&gt;~string();                      // call the object's dtor
</PRE>
</UL><A NAME="34319"></A>
<UL><PRE>
operator delete(ps);                // deallocate the memory
                                    // the object occupied
</PRE>
</UL><A NAME="11540"></A>
<P><A NAME="dingp28"></A>
One implication of this is that if you want to deal only with raw, uninitialized memory, you should bypass the <CODE>new</CODE> and <CODE>delete</CODE> operators entirely. Instead, you should call <CODE>operator</CODE> <CODE>new</CODE> to get the memory and <CODE>operator</CODE> <CODE>delete</CODE> to return it to the <NOBR>system:<SCRIPT>create_link(28);</SCRIPT>
</NOBR></p><A NAME="34551"></A>
<UL><PRE>
void *buffer =                      // allocate enough
  operator new(50*sizeof(char));    // memory to hold 50
                                    // chars; call no ctors
</PRE>
</UL><A NAME="34554"></A>
<UL><PRE>...
</PRE>
</UL><A NAME="34555"></A>
<UL><PRE>
operator delete(buffer);            // deallocate the memory;
                                    // call no dtors
</PRE>
</UL><A NAME="34561"></A>
<A NAME="p42"></A><P><A NAME="dingp29"></A>
This is the C++ equivalent of calling <CODE>malloc</CODE> and <CODE>free</CODE>.<SCRIPT>create_link(29);</SCRIPT>
</p><A NAME="40822"></A>
<P><A NAME="dingp30"></A>
If you use placement <CODE>new</CODE> to create an object in some memory, you should avoid using the <CODE>delete</CODE> operator on that memory. That's because the <CODE>delete</CODE> operator calls <CODE>operator</CODE> <CODE>delete</CODE> to deallocate the memory, but the memory containing the object wasn't allocated by <CODE>operator</CODE> <CODE>new</CODE> in the first place; placement <CODE>new</CODE> just returned the pointer that was passed to it. Who knows where that pointer came from? Instead, you should undo the effect of the constructor by explicitly calling the object's <NOBR>destructor:<SCRIPT>create_link(30);</SCRIPT>
</NOBR></p><A NAME="40835"></A>
<UL><PRE>// functions for allocating and deallocating memory in
// shared memory
void * mallocShared(size_t size);
void freeShared(void *memory);
</PRE>
</UL><A NAME="40848"></A>
<UL><PRE>void *sharedMemory = mallocShared(sizeof(Widget));
</PRE>
</UL><A NAME="64775"></A>
<UL><PRE>
Widget *pw =                                   // as above,
  constructWidgetInBuffer(sharedMemory, 10);   // placement
                                               // new is used
</PRE>
</UL><A NAME="40850"></A>
<UL><PRE>...
</PRE>
</UL><A NAME="64856"></A>
<UL><PRE>
delete pw;            // undefined! sharedMemory came from
                      // mallocShared, not operator new
</PRE>
</UL><A NAME="40852"></A>
<UL><PRE>
pw-&gt;~Widget();        // fine, destructs the Widget pointed to
                      // by pw, but doesn't deallocate the
                      // memory containing the Widget
</PRE>
</UL><A NAME="64861"></A>
<UL><PRE>
freeShared(pw);       // fine, deallocates the memory pointed
                      // to by pw, but calls no destructor
</PRE>
</UL><A NAME="40880"></A>
<P><A NAME="dingp31"></A>
As this example demonstrates, if the raw memory passed to placement <CODE>new</CODE> was itself dynamically allocated (through some unconventional means), you must still deallocate that memory if you wish to avoid a memory leak. (See <A HREF="../MAGAZINE/CO_FRAME.HTM#sidebar" TARGET="_top">the sidebar</A> to <A HREF="../MAGAZINE/CO_FRAME.HTM" TARGET="_top">my article on counting objects</A> for information on "placement <CODE>delete</CODE>".)<SCRIPT>create_link(31);</SCRIPT>
</p>

<P><A NAME="dingp32"></A><font ID="mhtitle">Arrays</font><SCRIPT>create_link(32);</SCRIPT>
</P>

<A NAME="34320"></A>
<P><A NAME="dingp33"></A>
So far so good, but there's farther to go. Everything we've examined so far concerns itself with only one object at a time. What about array allocation? What happens <NOBR>here?<SCRIPT>create_link(33);</SCRIPT>
</NOBR></p><A NAME="34326"></A>
<UL><PRE>
string *ps = new string[10];          // allocate an array of
                                      // objects
</PRE>
</UL><A NAME="34331"></A>
<P><A NAME="dingp34"></A>
The <CODE>new</CODE> being used is still the <CODE>new</CODE> operator, but because an array is being created, the <CODE>new</CODE> operator behaves slightly differently from the case of single-object creation. For one thing, memory is no longer allocated by <CODE>operator</CODE> <CODE>new</CODE>. Instead, it's allocated by the array-allocation equivalent, a function called <CODE>operator</CODE> <CODE><NOBR>new[]</NOBR></CODE> (often referred to as <A NAME="p43"></A>"array <CODE>new</CODE>.") Like <CODE>operator</CODE> <CODE>new</CODE>, <CODE>operator</CODE> <CODE><NOBR>new[]</NOBR></CODE> can be overloaded. This allows you to seize control of memory allocation for arrays in the same way you can control memory allocation for single objects (but see <A HREF="../EC/EI8_FR.HTM#120851" TARGET="_top">Item E8</A> for some caveats on <NOBR>this).<SCRIPT>create_link(34);</SCRIPT>
</NOBR></p><A NAME="64875"></A>
<P><A NAME="dingp35"></A>
(<CODE>operator</CODE> <CODE><NOBR>new[]</NOBR></CODE> is a relatively recent addition to C++, so your compilers may not support it yet. If they don't, the global version of <CODE>operator</CODE> <CODE>new</CODE> will be used to allocate memory for every array, regardless of the type of objects in the array. Customizing array-memory allocation under such compilers is daunting, because it requires that you rewrite the global <CODE>operator</CODE> <CODE>new</CODE>. This is not a task to be undertaken lightly. By default, the global <CODE>operator</CODE> <CODE>new</CODE> handles <I>all</I> dynamic memory allocation in a program, so any change in its behavior has a dramatic and pervasive effect. Furthermore, there is only one global <CODE>operator</CODE> <CODE>new</CODE> with the "normal" signature (i.e., taking the single <CODE>size_t</CODE> parameter &#151; see <A HREF="../EC/EI9_FR.HTM#1961" TARGET="_top">Item E9</A>), so if you decide to claim it as your own, you instantly render your software incompatible with any library that makes the same decision. (See also <A HREF="./MI27_FR.HTM#22627" TARGET="_top">Item 27</A>.) As a result of these considerations, custom memory management for arrays is not usually a reasonable design decision for compilers lacking support for <CODE>operator</CODE> <CODE><NOBR>new[]</NOBR></CODE>.)<SCRIPT>create_link(35);</SCRIPT>
</p><A NAME="7340"></A>
<P><A NAME="dingp36"></A>
The second way in which the <CODE>new</CODE> operator behaves differently for arrays than for objects is in the number of constructor calls it makes. For arrays, a constructor must be called for <I>each object</I> in the <NOBR>array:<SCRIPT>create_link(36);</SCRIPT>
</NOBR></p><A NAME="34387"></A>
<UL><PRE>
string *ps =               // call operator <NOBR>new[]</NOBR> to allocate
  new string[10];          // memory for 10 string objects,
                           // then call the default string
                           // ctor for each array element
</PRE>
</UL><A NAME="34388"></A>
<P><A NAME="dingp37"></A>
Similarly, when the <CODE>delete</CODE> operator is used on an array, it calls a destructor for each array element and then calls <CODE>operator</CODE> <CODE><NOBR>delete[]</NOBR></CODE> to deallocate the <NOBR>memory:<SCRIPT>create_link(37);</SCRIPT>
</NOBR></p><A NAME="34382"></A>
<UL><PRE>
delete [] ps;              // call the string dtor for each
                           // array element, then call
                           // operator <NOBR>delete[]</NOBR> to
                           // deallocate the array's memory
</PRE>
</UL><A NAME="34393"></A>
<P><A NAME="dingp38"></A>
Just as you can replace or overload <CODE>operator</CODE> <CODE>delete</CODE>, you can replace or overload <CODE>operator</CODE> <CODE><NOBR>delete[]</NOBR></CODE>. There are some restrictions on how they can be overloaded, however; consult a good C++ text for details. (For ideas on good C++ texts, see the recommendations beginning on <a href="./MIREADFR.HTM#books" TARGET="_top">page 285</A>.)<SCRIPT>create_link(38);</SCRIPT>
</p><A NAME="34449"></A>
<P><A NAME="dingp39"></A>
So there you have it. The <CODE>new</CODE> and <CODE>delete</CODE> operators are built-in and beyond your control, but the memory allocation and deallocation functions they call are not. When you think about customizing the behavior of the <CODE>new</CODE> and <CODE>delete</CODE> operators, remember that you can't really do it. You can modify <I>how</I> they do what they do, but what they do is fixed by the <NOBR>language.<SCRIPT>create_link(39);</SCRIPT>
</NOBR></p>

<DIV ALIGN="CENTER"><FONT SIZE="-1">Back to <A HREF="./MI7_FR.HTM" TARGET="_top">Item 7: Never overload &&, ||, or ,</A> &nbsp;&nbsp;<BR>&nbsp;&nbsp;Continue to <A HREF="./MEXCEPFR.HTM" TARGET="_top">Exceptions</A></FONT></DIV>
</BODY>
</HTML>

⌨️ 快捷键说明

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