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

📄 mi8.htm

📁 一个非常适合初学者入门的有关c++的文档
💻 HTM
📖 第 1 页 / 共 2 页
字号:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Frameset//EN" "http://www.w3.org/TR/REC-html40/frameset.dtd">
<HTML LANG="EN">
<HEAD>
<TITLE>More Effective C++ | Item 8: Understand the different meanings of new and delete</TITLE>
<LINK REL=STYLESHEET HREF=../INTRO/ECMEC.CSS>

<SCRIPT LANGUAGE="Javascript" SRC="../JAVA/COOKIE.JS"></SCRIPT>
<SCRIPT LANGUAGE="Javascript">var imagemax = 0; setCurrentMax(0);</SCRIPT>
<SCRIPT LANGUAGE="Javascript" SRC="../JAVA/DINGBATS.JS"></SCRIPT>
<SCRIPT LANGUAGE="Javascript">var dingbase = "MI8_DIR.HTM";
var dingtext = "Item M8, P";
if (self == top) {
 top.location.replace(dingbase + this.location.hash);
}</SCRIPT>

</HEAD>
<BODY BGCOLOR="#FFFFFF" TEXT="#000000" ONLOAD="setResize()">
<!-- SectionName = "M8: The different meanings of new and delete" -->
<A NAME="33985"></A>
<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>


<P><A NAME="dingp1"></A><font ID="mititle">Item 8: &nbsp;Understand the different meanings of <CODE>new</CODE>
and <CODE>delete</CODE>.</font><SCRIPT>create_link(1);</SCRIPT>
</P>

<A NAME="72115"></A>
<A NAME="34122"></A>
<P><A NAME="dingp2"></A>
It occasionally seems as if people went out of their way to make C++ terminology difficult to understand. Case in point: the difference between the <CODE><I>new</I></CODE> <I>operator</I> and <CODE><I>operator</I></CODE> <CODE><I>new</I></CODE>.<SCRIPT>create_link(2);</SCRIPT>
</p>
<A NAME="34062"></A>

<P><A NAME="dingp3"></A>When you write code like <NOBR>this,<SCRIPT>create_link(3);</SCRIPT>
</NOBR></P>
<A NAME="34094"></A>
<UL><PRE>string *ps = new string("Memory Management");
</PRE>
</UL><A NAME="34095"></A><P><A NAME="dingp4"></A>
the <CODE>new</CODE> you are using is the <CODE>new</CODE> operator. This operator is built into the language and, like <CODE>sizeof</CODE>, you can't change its meaning: it always does the same thing. What it does is twofold. First, it allocates enough memory to hold an object of the type requested. In the example above, it allocates enough memory to hold a <CODE>string</CODE> object. Second, it calls a constructor to initialize an object in the memory that was allocated. The <CODE>new</CODE> operator always does those two things; you can't change its behavior in any <NOBR>way.<SCRIPT>create_link(4);</SCRIPT>
</NOBR></p><A NAME="34137"></A>
<P><A NAME="dingp5"></A>
What you can change is <I>how</I> the memory for an object is allocated. The <CODE>new</CODE> operator calls a function to perform the requisite memory allocation, and you can rewrite or overload that function to change its behavior. The name of the function the <CODE>new</CODE> operator calls to allocate memory is <CODE>operator</CODE> <CODE>new</CODE>. <NOBR>Honest.<SCRIPT>create_link(5);</SCRIPT>
</NOBR></p><A NAME="34175"></A>
<P><A NAME="dingp6"></A>
The <CODE>operator</CODE> <CODE>new</CODE> function is usually declared like <NOBR>this:<SCRIPT>create_link(6);</SCRIPT>
</NOBR></p>
<A NAME="34176"></A>
<UL><PRE>void * operator new(size_t size);
</PRE>
</UL><A NAME="11461"></A>
<P><A NAME="dingp7"></A>
The return type is <CODE>void*</CODE>, because this function returns a pointer to raw, uninitialized memory. (If you like, you can write a version of <CODE>operator</CODE> <CODE>new</CODE> that initializes the memory to some value before returning a pointer to it, but this is not commonly done.) The <CODE>size_t</CODE> parameter specifies how much memory to allocate. You can overload <CODE>operator</CODE> <A NAME="p39"></A><CODE>new</CODE> by adding additional parameters, but the first parameter must always be of type <CODE>size_t</CODE>. (For information on writing <CODE>operator</CODE> <CODE>new</CODE>, consult Items <A HREF="../EC/EI8_FR.HTM#120851" TARGET="_top">E8</A>-<A HREF="../EC/EI10_FR.HTM#1986" TARGET="_top">E10</A>.)<SCRIPT>create_link(7);</SCRIPT>
</p><A NAME="11467"></A>
<P><A NAME="dingp8"></A>
You'll probably never want to call <CODE>operator</CODE> <CODE>new</CODE> directly, but on the off chance you do, you'll call it just like any other <NOBR>function:<SCRIPT>create_link(8);</SCRIPT>
</NOBR></p><A NAME="64753"></A>
<UL><PRE>void *rawMemory = operator new(sizeof(string));
</PRE>
</UL><A NAME="64754"></A>
<P><A NAME="dingp9"></A>
Here <CODE>operator</CODE> <CODE>new</CODE> will return a pointer to a chunk of memory large enough to hold a <CODE>string</CODE> <NOBR>object.<SCRIPT>create_link(9);</SCRIPT>
</NOBR></p>
<A NAME="34195"></A>

<P><A NAME="dingp10"></A>Like <CODE>malloc</CODE>, <CODE>operator</CODE> <CODE>new</CODE>'s only responsibility is to allocate memory. It knows nothing about constructors. All <CODE>operator</CODE> <CODE>new</CODE> understands is memory allocation. It is the job of the <CODE>new</CODE> operator to take the raw memory that <CODE>operator</CODE> <CODE>new</CODE> returns and transform it into an object. When your compilers see a statement <NOBR>like<SCRIPT>create_link(10);</SCRIPT>
</NOBR></P>
<A NAME="34209"></A>
<UL><PRE>string *ps = new string("Memory Management");
</PRE>
</UL><A NAME="34207"></A><P><A NAME="dingp11"></A>they must generate code that more or less corresponds to this (see Items <A HREF="../EC/EI8_FR.HTM#120851" TARGET="_top">E8</A> and <A HREF="../EC/EI10_FR.HTM#1986" TARGET="_top">E10</A>, as well as <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 a more detailed treatment of this <NOBR>point):<SCRIPT>create_link(11);</SCRIPT>
</NOBR></p><A NAME="34212"></A>
<UL><PRE>
void *memory =                              // get raw memory
  operator new(sizeof(string));             // for a string
                                            // object
</PRE>
</UL><A NAME="34213"></A>
<UL><PRE>
<i>call string::string("Memory Management")</i>    // initialize the
<i>on *memory;</i>                                 // object in the
                                            // memory
</PRE>
</UL><A NAME="34214"></A>
<UL><PRE>
string *ps =                                // make ps point to
  static_cast&lt;string*&gt;(memory);             // the new object
</PRE>
</UL><A NAME="34239"></A>

<P><A NAME="dingp12"></A>Notice that the second step above involves calling a constructor, something you, a mere programmer, are prohibited from doing. Your compilers are unconstrained by mortal limits, however, and they can do whatever they like. That's why you must use the <CODE>new</CODE> operator if you want to conjure up a heap-based object: you can't directly call the constructor necessary to initialize the object (including such crucial components as its vtbl &#151; see <A HREF="./MI24_FR.HTM#41284" TARGET="_top">Item 24</A>).<SCRIPT>create_link(12);</SCRIPT>
</p>

<P><A NAME="dingp13"></A><font ID="mhtitle">Placement <CODE>new</CODE></font><SCRIPT>create_link(13);</SCRIPT>
</P>

<A NAME="40577"></A>
<P><A NAME="dingp14"></A>There are times when you really <I>want</I> to call a constructor directly. Invoking a constructor on an existing object makes no sense, because constructors initialize objects, and an object can only be initialized &#151; given its first value &#151; once. But occasionally you have some raw memory that's already been allocated, and you need to construct an object in the memory you have. A special version of <CODE>operator</CODE> <CODE>new</CODE> called <I>placement</I> <CODE><I>new</I></CODE> allows you to do <NOBR>it.<SCRIPT>create_link(14);</SCRIPT>
</NOBR></p>

<A NAME="40747"></A>
<P><A NAME="dingp15"></A>As an example of how placement <CODE>new</CODE> might be used, consider <NOBR>this:<SCRIPT>create_link(15);</SCRIPT>
</NOBR></p><A NAME="40580"></A>
<A NAME="p40"></A><UL><PRE>class Widget {
public:
  Widget(int widgetSize);
  ...
};
</PRE>
</UL><A NAME="79219"></A>
<UL><PRE>Widget * constructWidgetInBuffer(void *buffer,
                                 int widgetSize)
{
  return new (buffer) Widget(widgetSize);
}
</PRE>
</UL><A NAME="40622"></A>

<P><A NAME="dingp16"></A>This function returns a pointer to a <CODE>Widget</CODE> object that's constructed <I>within</I> the buffer passed to the function. Such a function might be useful for applications using shared memory or memory-mapped I/O, because objects in such applications must be placed at specific addresses or in memory allocated by special routines. (For a different example of how placement <CODE>new</CODE> can be used, see <A HREF="./MI4_FR.HTM#5218" TARGET="_top">Item 4</A>.)<SCRIPT>create_link(16);</SCRIPT>
</p><A NAME="40641"></A>

<P><A NAME="dingp17"></A>Inside <CODE>constructWidgetInBuffer</CODE>, the expression being returned <NOBR>is<SCRIPT>create_link(17);</SCRIPT>
</NOBR></p><A NAME="40598"></A>
<UL><PRE>new (buffer) Widget(widgetSize)
</PRE>
</UL><A NAME="40603"></A>

<P><A NAME="dingp18"></A>This looks a little strange at first, but it's just a use of the <CODE>new</CODE> operator in which an additional argument (<CODE>buffer</CODE>) is being specified for the implicit call that the <CODE>new</CODE> operator makes to <CODE>operator</CODE> <CODE>new</CODE>. The <CODE>operator</CODE> <CODE>new</CODE> thus called must, in addition to the mandatory <CODE>size_t</CODE> argument, accept a <CODE>void*</CODE> parameter that points to the memory the object being constructed is to occupy. That <CODE>operator</CODE> <CODE>new</CODE> <I>is</I> placement <CODE>new</CODE>, and it looks like <NOBR>this:<SCRIPT>create_link(18);</SCRIPT>
</NOBR></p>
<A NAME="40666"></A>
<UL><PRE>void * operator new(size_t, void *location)
{
  return location;
}
</PRE>
</UL><A NAME="10060"></A>
<P><A NAME="dingp19"></A>This is probably simpler than you expected, but this is all placement <CODE>new</CODE> needs to do. After all, the purpose of <CODE>operator</CODE> <CODE>new</CODE> is to find memory for an object and return a pointer to that memory. In the case of placement <CODE>new</CODE>, the caller already knows what the pointer to the memory should be, because the caller knows where the object is supposed to be placed. All placement <CODE>new</CODE> has to do, then, is return the pointer that's passed into it. (The unused (but mandatory) <CODE>size_t</CODE> parameter has no name to keep compilers from complaining about its not being used; see <A HREF="./MI6_FR.HTM#5262" TARGET="_top">Item 6</A>.) Placement <CODE>new</CODE> is part of the standard C++ library (see <A HREF="../EC/EI49_FR.HTM#8392" TARGET="_top">Item E49</A>). To use placement <CODE>new</CODE>, all you have to do is <CODE>#include</CODE> <CODE>&lt;new&gt;</CODE> (or, if your compilers don't yet support the new-style header names (again, see <A HREF="../EC/EI49_FR.HTM#8392" TARGET="_top">Item E49</A>), <CODE>&lt;new.h&gt;</CODE>).<SCRIPT>create_link(19);</SCRIPT>
</p><A NAME="10068"></A>
<P><A NAME="dingp20"></A>
If we step back from placement <CODE>new</CODE> for a moment, we'll see that the relationship between the <CODE>new</CODE> operator and <CODE>operator</CODE> <CODE>new</CODE>, though
<A NAME="12055"></A><A NAME="p41"></A>you want to create an object on the heap, use the <CODE>new</CODE> operator. It both allocates memory and calls a constructor for the object. If you only want to allocate memory, call <CODE>operator</CODE> <CODE>new</CODE>; no constructor will be called. If you want to customize the memory allocation that takes place when heap objects are created, write your own version of <CODE>operator</CODE> <CODE>new</CODE> and use the <CODE>new</CODE> operator; it will automatically invoke your custom version of <CODE>operator</CODE> <CODE>new</CODE>. If you want to construct an object in memory you've already got a pointer to, use placement <CODE>new</CODE>.<SCRIPT>create_link(20);</SCRIPT>
</p><A NAME="11516"></A>
<P><A NAME="dingp21"></A>
(For additional insights into variants of <CODE>new</CODE> and <CODE>delete</CODE>, see <A HREF="../EC/EI7_FR.HTM#1894" TARGET="_top">Item E7</A> and <A HREF="../MAGAZINE/CO_FRAME.HTM" TARGET="_top">my article on counting objects</A>.)<SCRIPT>create_link(21);</SCRIPT>
</p>

<P><A NAME="dingp22"></A><font ID="mhtitle">Deletion and Memory Deallocation</font><SCRIPT>create_link(22);</SCRIPT>
</P>

⌨️ 快捷键说明

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