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

📄 chapter13.html

📁 《C++编程思想》中文版。。。。。。。。。。。。。
💻 HTML
📖 第 1 页 / 共 5 页
字号:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<!--
This document was converted from RTF source: 
By rtftohtml 4.19
See http://www.sunpack.com/RTF
Filename:TIC2Vone.rtf
Application Directory:C:\TOOLS\RTF2HTML\
Subject:
Author:Bruce Eckel
Operator:Bruce Eckel
Document Comments:
Version Comments:
Comments:
Keywords:
Translation Date:09/27/2001
Translation Time:05:25:50
Translation Platform:Win32
Number of Output files:22
This File:Chapter13.html
SplitDepth=1
SkipNavPanel=1
SkipLeadingToc=1
SkipTrailingToc=1
GenContents=1
GenFrames=1
GenIndex=1
-->
<HEAD lang="en"><META http-equiv="Content-Type" content="text/html">
<TITLE>13: Dynamic Object Creation</TITLE>
</HEAD>

<BODY  BGCOLOR="#FFFFFF"><DIV ALIGN="CENTER">
  <a href="http://www.MindView.net">
  <img src="mindview-head.gif" alt="MindView Inc." BORDER = "0"></a>
  <CENTER>
    <FONT FACE="Verdana" size = "-1">
    [ <a href="README-HTML.txt">Viewing Hints</a> ]
    [ <a href="http://www.mindview.net/CPPServices/SolutionGuide.html">Exercise Solutions</a> ]
    [ <a href="http://www.mindview.net/ThinkingInCPP2e.html">Volume 2</a> ]
    [ <a href="http://www.mindview.net/MailingList.html">Free Newsletter</a> ] <br>
    [ <a href="http://www.mindview.net/CPPServices/#PublicSeminars">Seminars</a> ]
    [ <a href="http://www.mindview.net/CPPServices/#SeminarsOnCD">Seminars on CD ROM</a> ]
    [ <a href="http://www.mindview.net/CPPServices/#ConsultingServices">Consulting</a> ]
    </FONT>
  <H2><FONT FACE="Verdana">
  Thinking in C++, 2nd ed. Volume 1</FONT></H2></FONT>
  <H3><FONT FACE="Verdana">&copy;2000 by Bruce Eckel</FONT></H3></FONT>
  
    <FONT FACE="Verdana" size = "-1">
     [ <a href="Chapter12.html">Previous Chapter</a> ] 
    [ <a href="Contents.html">Table of Contents</a> ] 
    [ <a href="DocIndex.html">Index</a> ]
     [ <a href="Chapter14.html">Next Chapter</a> ] 
    </FONT>
    
  </CENTER>
  </P></DIV><A NAME="_Toc472654966"></A><A NAME="Heading381"></A><FONT FACE = "Verdana"><H1 ALIGN="LEFT">
13: Dynamic Object Creation</H1></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Verdana" SIZE=4>Sometimes you know the exact
quantity, type, and lifetime<A NAME="Index2132"></A><A NAME="Index2133"></A> of
the objects in your program. But not
always.<A NAME="Index2134"></A></FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">How many planes will an air-traffic
system need to handle? How many shapes will a CAD system use? How many nodes
will there be in a network?</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">To solve the general programming problem,
it&#8217;s essential that you be able to create and destroy objects at runtime.
Of course, C has always provided the <I>dynamic memory allocation</I> functions
<A NAME="Index2135"></A><A NAME="Index2136"></A><A NAME="Index2137"></A><B>malloc(&#160;)
</B>and <B>free(&#160;) </B>(along with variants of <B>malloc(&#160;)</B>) that
allocate storage from the <I>heap</I> (also called the <I>free store</I>) at
runtime.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">However, this simply won&#8217;t work in
C++. The constructor <A NAME="Index2138"></A>doesn&#8217;t allow you to hand it
the address of the memory to initialize, and for good reason. If you could do
that, you
might<A NAME="Index2139"></A><A NAME="Index2140"></A>:</FONT><BR></P></DIV>
<OL>
<LI><FONT FACE="Verdana">	</FONT><FONT FACE="Georgia">Forget. Then guaranteed
initialization of objects in C++ wouldn&#8217;t be
guaranteed.</FONT><LI><FONT FACE="Verdana">	</FONT><FONT FACE="Georgia">Accidentally
do something to the object before you initialize it, expecting the right thing
to happen.</FONT><LI><FONT FACE="Verdana">	</FONT><FONT FACE="Georgia">Hand it
the wrong-sized object.</FONT></OL><DIV ALIGN="LEFT"><P><FONT FACE="Georgia">And of
course, even if you did everything correctly, anyone who modifies your program
is prone to the same errors. Improper initialization is responsible for a large
portion of programming problems, so it&#8217;s especially important to guarantee
constructor calls for objects created on the heap.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">So how does C++ guarantee proper
<A NAME="Index2141"></A><A NAME="Index2142"></A><A NAME="Index2143"></A><A NAME="Index2144"></A>initialization
and cleanup, but allow you to create objects dynamically on the
heap?</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">The answer is by bringing dynamic object
creation into the core of the language. <B>malloc(&#160;)</B> and
<B>free(&#160;)</B> are library functions, and thus outside the control of the
compiler. However, if you have an <I>operator</I> to perform the combined act of
dynamic storage allocation and initialization and another operator to perform
the combined act of cleanup and releasing storage, the compiler can still
guarantee that constructors and destructors will be called for all
objects.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">In this chapter, you&#8217;ll learn how
C++&#8217;s <B>new</B> and <B>delete</B> elegantly solve this problem by safely
creating objects on the
heap.</FONT><A NAME="_Toc305593243"></A><A NAME="_Toc305628715"></A><A NAME="_Toc312373992"></A><A NAME="_Toc472654967"></A><BR></P></DIV>
<A NAME="Heading382"></A><FONT FACE = "Verdana"><H2 ALIGN="LEFT">
Object creation</H2></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">When a C++ object is created, two events
occur:</FONT><BR></P></DIV>
<OL>
<LI><FONT FACE="Verdana">	</FONT><FONT FACE="Georgia">Storage is allocated for
the object.</FONT><LI><FONT FACE="Verdana">	</FONT><FONT FACE="Georgia">The
constructor is called to initialize that
storage.</FONT></OL><DIV ALIGN="LEFT"><P><FONT FACE="Georgia">By now you should
believe that step two <I>always</I> happens. C++ enforces it because
uninitialized objects are a major source of program bugs. It doesn&#8217;t
matter where or how the object is created &#8211; the constructor is always
called.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Step one, however, can occur in several
ways, or at alternate
times<A NAME="Index2145"></A><A NAME="Index2146"></A><A NAME="Index2147"></A><A NAME="Index2148"></A><A NAME="Index2149"></A><A NAME="Index2150"></A><A NAME="Index2151"></A><A NAME="Index2152"></A>:</FONT><BR></P></DIV>
<OL>
<LI><FONT FACE="Verdana">	</FONT><FONT FACE="Georgia">Storage can be allocated
before the program begins, in the static storage area. This storage exists for
the life of the
program.</FONT><LI><FONT FACE="Verdana">	</FONT><FONT FACE="Georgia">Storage can
be created on the stack whenever a particular execution point is reached (an
opening brace). That storage is released automatically at the complementary
execution point (the closing brace). These stack-allocation operations are built
into the instruction set of the processor and are very efficient. However, you
have to know exactly how many variables you need when you&#8217;re writing the
program so the compiler can generate the right
code.</FONT><LI><FONT FACE="Verdana">	</FONT><FONT FACE="Georgia">Storage can be
allocated from a pool of memory called the heap (also known as the free store).
This is called dynamic memory allocation. To allocate this memory, a function is
called at runtime; this means you can decide at any time that you want some
memory and how much you need. You are also responsible for determining when to
release the memory, which means the lifetime of that memory can be as long as
you choose &#8211; it isn&#8217;t determined by
scope.</FONT></OL><DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Often these three
regions are placed in a single contiguous piece of physical memory: the static
area, the stack, and the heap (in an order determined by the compiler writer).
However, there are no rules. The stack may be in a special place, and the heap
may be implemented by making calls for chunks of memory from the operating
system. As a programmer, these things are normally shielded from you, so all you
need to think about is that the memory is there when you call for
it.</FONT><A NAME="_Toc312373993"></A><A NAME="_Toc472654968"></A><BR></P></DIV>
<A NAME="Heading383"></A><FONT FACE = "Verdana"><H3 ALIGN="LEFT">
C&#8217;s approach to the heap</H3></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">To allocate memory dynamically at
runtime, C provides functions in its standard library:
<B>malloc(&#160;)<A NAME="Index2153"></A></B> and its variants
<B>calloc(&#160;)<A NAME="Index2154"></A></B> and
<B>realloc(&#160;)<A NAME="Index2155"></A></B> to produce memory from the
heap<A NAME="Index2156"></A><A NAME="Index2157"></A>, and
<B>free(&#160;)<A NAME="Index2158"></A></B> to release the memory back to the
heap. These functions are pragmatic but primitive and require understanding and
care on the part of the programmer. To create an instance of a class on the heap
using C&#8217;s dynamic memory functions, you&#8217;d have to do something like
this:</FONT><BR></P></DIV>

<BLOCKQUOTE><FONT SIZE = "+1"><PRE><font color=#009900>//: C13:MallocClass.cpp</font>
<font color=#009900>// Malloc with class objects</font>
<font color=#009900>// What you'd have to do if not for "new"</font>
#include <font color=#004488>"../require.h"</font>
#include &lt;cstdlib&gt; <font color=#009900>// malloc() &amp; free()</font>
#include &lt;cstring&gt; <font color=#009900>// memset()</font>
#include &lt;iostream&gt;
<font color=#0000ff>using</font> <font color=#0000ff>namespace</font> std;

<font color=#0000ff>class</font> Obj {
  <font color=#0000ff>int</font> i, j, k;
  <font color=#0000ff>enum</font> { sz = 100 };
  <font color=#0000ff>char</font> buf[sz];
<font color=#0000ff>public</font>:
  <font color=#0000ff>void</font> initialize() { <font color=#009900>// Can't use constructor</font>
    cout &lt;&lt; <font color=#004488>"initializing Obj"</font> &lt;&lt; endl;
    i = j = k = 0;
    memset(buf, 0, sz);
  }
  <font color=#0000ff>void</font> destroy() <font color=#0000ff>const</font> { <font color=#009900>// Can't use destructor</font>
    cout &lt;&lt; <font color=#004488>"destroying Obj"</font> &lt;&lt; endl;
  }
};

<font color=#0000ff>int</font> main() {
  Obj* obj = (Obj*)malloc(<font color=#0000ff>sizeof</font>(Obj));
  require(obj != 0);
  obj-&gt;initialize();
  <font color=#009900>// ... sometime later:</font>
  obj-&gt;destroy();
  free(obj);
} <font color=#009900>///:~</font></PRE></FONT></BLOCKQUOTE>

<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">You can see the use of
<B>malloc(&#160;)</B> to create storage for the object in the
line:</FONT><BR></P></DIV>
<BLOCKQUOTE><FONT SIZE = "+1"><PRE>Obj* obj = (Obj*)malloc(<font color=#0000ff>sizeof</font>(Obj));</PRE></FONT></BLOCKQUOTE>

<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Here, the user must determine the size of
the object (one place for an error). <B>malloc(&#160;)</B> returns a
<B>void*</B> because it just produces a patch of memory, not an object. C++
doesn&#8217;t allow a <B>void*</B> to be assigned to any other pointer, so it
must be cast.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Because <B>malloc(&#160;)</B> may fail to
find any memory (in which case it returns zero), you must check the returned
pointer to make sure it was successful.</FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">But the worst problem is this

⌨️ 快捷键说明

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