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

📄 index.html

📁 C程序员手册(英文)
💻 HTML
📖 第 1 页 / 共 4 页
字号:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
<HTML>

<HEAD>
	<META NAME="Author" Content="Steph Mineart">
	<META HTTP-EQUIV="Content-Type" CONTENT="text/html;CHARSET=iso-8859-1">
	<TITLE>ANSI/ISO C++ Professional Programmer's Handbook - Chapter 11 - Memmory Management</TITLE>
	<link rel="stylesheet"  TYPE="text/css" href="/includes/stylesheets/ebooks.css">
</head>

<BODY TEXT="#000000" BGCOLOR="#FFFFFF">

<CENTER>
<H1><img src="/publishers/que/series/professional/0789720221/button/que.gif" WIDTH="171" HEIGHT="66" ALIGN="BOTTOM" BORDER="0"><BR>
ANSI/ISO C++ Professional Programmer's Handbook</H1>
</CENTER>
<CENTER>
  <P><A HREF="/publishers/que/series/professional/0789720221/index.htm"><img src="/publishers/que/series/professional/0789720221/button/contents.gif" WIDTH="128"
HEIGHT="28" ALIGN="BOTTOM" ALT="Contents" BORDER="0"></A> 
  <HR>
</CENTER>
<H1 align="center">11</H1>
<h1 align="center"> Memory Management</h1>
<address>by Danny Kalev</address>
<ul>
  <li><a href="#Heading1">Introduction</a> 
  <li><a href="#Heading2">Types of Storage</a> 
    <ul>
      <li><a href="#Heading3">Automatic Storage</a> 
      <li><a href="#Heading4">Static Storage</a> 
      <li><a href="#Heading5">Free Store</a> 
    </ul>
  <li><a href="#Heading6">POD (Plain Old Data) and non-POD Objects</a> 
  <li><a href="#Heading7">The Lifetime of a POD Object</a> 
  <li><a href="#Heading8">The Lifetime of a non-POD Object</a> 
  <li><a href="#Heading9">Allocation and Deallocation Functions</a> 
    <ul>
      <li><a href="#Heading10">Semantics of Allocation Functions</a> 
      <li><a href="#Heading11">Semantics of Deallocation Functions</a> 
    </ul>
  <li><a href="#Heading12">malloc() and free() Versus new and delete</a> 
    <ul>
      <li><a href="#Heading13">Support For Object Semantics</a> 
      <li><a href="#Heading14">Safety</a> 
      <li><a href="#Heading15">Extensibility</a> 
    </ul>
  <li><a href="#Heading16">new and delete</a> 
    <ul>
      <li><a href="#Heading17">Allocating and Deallocating Arrays Using new[] 
        and delete[]</a> 
      <li><a href="#Heading18">Exceptions and Operator new</a> 
      <li><a href="#Heading19">Exception-Free Version of Operator new</a> 
      <li><a href="#Heading20">Placement new</a> 
    </ul>
  <li><a href="#Heading21">Exceptions During Object Construction</a> 
  <li><a href="#Heading22">Alignment Considerations</a> 
    <ul>
      <li><a href="#Heading23">Member Alignment</a> 
    </ul>
  <li><a href="#Heading24">The Size Of A Complete Object Can Never Be Zero</a> 
  <li><a href="#Heading25">User-Defined Versions of new and delete Cannot Be Declared 
    in a Namespace</a> 
  <li><a href="#Heading26">Overloading new and delete in a Class</a> 
  <li><a href="#Heading27">Guidelines for Effective Memory Usage</a> 
    <ul>
      <li><a href="#Heading28">Prefer Automatic Storage to Free Store Whenever 
        Possible</a> 
      <li><a href="#Heading29">Correct Syntax for Local Object Instantiation</a> 
      <li><a href="#Heading30">Zero As A Universal Initializer</a> 
      <li><a href="#Heading31">Always Initialize Pointers</a> 
    </ul>
  <li><a href="#Heading32">Explicit Initializations of POD Object</a> 
    <ul>
      <li><a href="#Heading33">Initializing Local Automatic Structs and Arrays</a> 
      <li><a href="#Heading34">Union Initialization</a> 
      <li><a href="#Heading35">Detecting a Machine's Endian</a> 
      <li><a href="#Heading36">The Lifetime Of A Bound Temporary Object</a> 
      <li><a href="#Heading37">Deleting A Pointer More Than Once</a> 
    </ul>
  <li><a href="#Heading38">Data Pointers Versus Function Pointers</a> 
  <li><a href="#Heading39">Pointer Equality</a> 
  <li><a href="#Heading40">Storage Reallocation</a> 
  <li><a href="#Heading41">Local Static Variables</a> 
  <li><a href="#Heading42">Global Anonymous Unions</a> 
  <li><a href="#Heading43">The const and volatile Properties of an Object</a> 
  <li><a href="#Heading44">Conclusions</a> 
</ul>
<hr size=4>
<h2> <a name="Heading1"> Introduction</a></h2>
<p>C++ added the necessary language constructs to the memory model of C to support 
  object semantics. In addition, it fixed some loopholes in the original model 
  and enhanced it with higher levels of abstraction and automation. This chapter 
  delves into the memory model of C++, starting with the three types of data storage. 
  Next, the various versions of operators <tt>new</tt> and <tt>delete</tt> are 
  discussed; finally, some techniques and guidelines for effective and bug-free 
  usage of the memory management constructs are presented.</p>
<h2> <a name="Heading2"> Types of Storage</a></h2>
<p>C++ has three fundamental types of data storage: automatic storage, static 
  storage, and free store. Each of these memory types has different semantics 
  of object initialization and lifetime.</p>
<h3> <a name="Heading3"> Automatic Storage</a></h3>
<p>Local objects that are not explicitly declared <tt>static</tt> or <tt>extern</tt>, 
  local objects that are declared <tt>auto</tt> or <tt>register</tt>, and function 
  arguments have <i>automatic storage</i>. This type of storage is also called 
  <i>stack memory</i>. Automatic objects are created automatically upon entering 
  a function or a block. They are destroyed when the function or block exits. 
  Thus, on each entry into a function or a block, a new copy of its automatic 
  objects is created. The default value of automatic variables and nonclass objects 
  is indeterminate.</p>
<h3> <a name="Heading4"> Static Storage</a></h3>
<p>Global objects, static data members of a class, namespace variables, and static 
  variables in functions reside in static memory.</p>
<p> The address of a static object remains the same throughout the program's execution. 
</p>
<p>Every static object is constructed only once during the lifetime of the program. 
  By default, static data are initialized to binary zeros. Static objects with 
  a <i>nontrivial constructor</i> (see Chapter 4, "Special Member Functions: Default 
  Constructor, Copy Constructor, Destructor, And Assignment Operator") are subsequently 
  initialized by their constructors. Objects with static storage are included 
  in the following examples:</p>
<pre>
<tt>int num; //global variables have static storage</tt>
<tt>int func()</tt>
<tt>{</tt>
<tt>  static int calls; //initialized to 0 by default</tt>
<tt>  return ++calls;</tt>
<tt>}</tt>
<tt>class C</tt>
<tt>{</tt>
<tt>private:</tt>
<tt>  static bool b;</tt>
<tt>};</tt>
<tt>namespace NS</tt>
<tt>{</tt>
<tt>  std::string str; //str has static storage </tt>
<tt>}</tt>
</pre>
<h3> <a name="Heading5"> Free Store</a></h3>
<p>Free store memory, also called <i>heap memory</i> or <i>dynamic memory</i>, 
  contains objects and variables that are created by operator <tt>new</tt>. Objects 
  and variables that are allocated on the free store persist until they are explicitly 
  released by a subsequent call to operator <tt>delete</tt>. The memory that is 
  allocated from the free store is not returned to the operating system automatically 
  after the program's termination. </p>
<p>Therefore, failing to release memory that was allocated using <tt>new</tt> 
  generally yields memory leaks. The address of an object that is allocated on 
  the free store is determined at runtime. The initial value of raw storage that 
  is allocated by <tt>new</tt> is unspecified.</p>
<h2> <a name="Heading6"> POD (Plain Old Data) and non-POD Objects</a></h2>
<p>A <i>POD</i> (<i>plain old data</i>) object has one of the following data types: 
  a fundamental type, pointer, union, struct, array, or class with a trivial constructor. 
  Conversely, a non-POD object is one for which a nontrivial constructor exists. 
  The properties of an object are in effect only during its <i>lifetime</i>.</p>
<h2> <a name="Heading7"> The Lifetime of a POD Object</a></h2>
<p>A POD object begins its lifetime when it obtains storage with the proper alignment 
  and size for its type, and its lifetime ends when the storage for the object 
  is either reused or deallocated. </p>
<h2> <a name="Heading8"> The Lifetime of a non-POD Object</a></h2>
<p>A non-POD object begins its lifetime after the constructor call has completed; 
  its lifetime ends when its destructor has started. </p>
<h2> <a name="Heading9"> Allocation and Deallocation Functions</a></h2>
<p>C++ defines the global <i>allocation functions</i> <tt>new</tt> and <tt>new[]</tt> 
  as well as the corresponding global <i>deallocation functions</i> <tt>delete</tt> 
  and <tt>delete[]</tt>. These functions are accessible from each translation 
  unit of a program without including the header <tt>&lt;new&gt;</tt>. Their implicit 
  declarations are as follows:</p>
<pre>
<tt>void* operator new(std::size_t) throw(std::bad_alloc);  // new</tt>
<tt>void* operator new[](std::size_t) throw(std::bad_alloc);  // new []</tt>
<tt>void operator delete(void*) throw();  // delete</tt>
<tt>void operator delete[](void*) throw();  // delete[]</tt>
</pre>
<p>The implicit declarations introduce only the function names operator <tt>new</tt>, 
  operator <tt>new[]</tt>, operator <tt>delete</tt>, and operator <tt>delete[]</tt>. 
  However, they do not introduce the names <tt>std</tt>, <tt>std::bad_alloc</tt>, 
  and <tt>std::size_t</tt>. An explicit reference to any of these names requires 
  that the appropriate header file be included. For example</p>
<pre>
<tt>#include &lt;new&gt; // declarations of std and size_t</tt>
<tt>using namespace std;</tt>
<tt>char * allocate (size_t bytes);</tt>
<tt>int main</tt>
<tt>{</tt>
<tt> char * buff = allocate(sizeof (char) );</tt>
<tt> return 0;</tt>
<tt>}</tt>
</pre>
<h3> <a name="Heading10"> Semantics of Allocation Functions</a></h3>
<p>The return type of an allocation function is <tt>void *</tt>, and its first 
  parameter is of type <tt>size_t</tt>. The value of the first parameter is interpreted 
  as the requested memory size. The allocation function attempts to allocate the 
  requested size of memory from the free store. If the allocation request is successful, 
  it returns the address of the start of a block of storage whose size, in bytes, 
  is at least as large as the requested size.</p>
<h3> <a name="Heading11"> Semantics of Deallocation Functions</a></h3>
<p>The return type of a deallocation function is <tt>void</tt>; its first parameter 
  is of type <tt>void *</tt>. A deallocation function can have more than one parameter. 
  The value of the first argument that is supplied to a deallocation function 
  can be <tt>NULL</tt> (in this case, the deallocation function call has no effect). 
  Otherwise, the value supplied to a deallocation function must be one of the 
  values returned by a previous invocation of a corresponding allocation function.Allocation 
  and deallocation functions perform the basic operations of allocating memory 
  from the free store and releasing it. Note however, that in general, you do 
  not invoke these functions directly. Rather, you use a <i>new expression</i> 
  and a <i>delete expression</i>. A new expression implicitly invokes an allocation 
  function and then constructs an object on the allocated memory; likewise, a 
  delete expression destroys an object, and then it invokes a deallocation function 
  to release the storage of the destroyed object.</p>
<blockquote>
  <hr>
  <strong>NOTE: </strong> In the following sections, <tt>new</tt> and <tt>delete</tt> 
  refer to a <tt>new</tt> expression and a <tt>delete</tt> expression, respectively, 
  unless stated otherwise. 
  <hr>
</blockquote>
<h2> <a name="Heading12"> malloc() and free() Versus new and delete</a></h2>
<p>C++ still supports the standard C library functions <tt>malloc()</tt> and <tt>free()</tt>. 
  The backward compatibility with C is useful in three cases: for combining legacy 
  code that was originally written in C in C++ programs, for writing C++ code 
  that is meant to be supported in C environment (more on this in Chapter 13, 
  "C Language Compatibility Issues"), and for making <tt>new</tt> and <tt>delete</tt> 
  implementable by calling <tt>malloc()</tt> and <tt>free()</tt>.</p>
<p>Otherwise, <tt>malloc()</tt> and <tt>free()</tt> are not to be used in C++ 
  code because -- unlike <tt>new</tt> and <tt>delete</tt> -- they do not support 
  object semantics. <tt>new</tt> and <tt>delete</tt> are also significantly safer 
  and more extensible.</p>
<h3> <a name="Heading13"> Support For Object Semantics</a></h3>
<p><tt>new</tt> and <tt>delete</tt> automatically construct and destroy objects. 
  <tt>malloc()</tt> and <tt>free()</tt>, on the other hand, merely allocate and 
  deallocate raw memory from the heap. In particular, using <tt>malloc()</tt> 
  to create a non-POD object yields undefined behavior. For example</p>
<pre>
<tt>#include &lt;cstdlib&gt;</tt>
<tt>#include &lt;string&gt;</tt>
<tt>using namespace std;</tt>
<tt>string* func() //very bad</tt>
<tt>{</tt>
<tt>  string *pstr = static_cast&lt;string*&gt; (malloc (sizeof(string))); //disaster!</tt>
<tt>  return pstr; //any attempt to use pstr as a pointer to a string is undefined</tt>
<tt>}</tt>
</pre>
<h3> <a name="Heading14"> Safety</a></h3>
<p>Operator <tt>new</tt> automatically calculates the size of the object that 
  it constructs. Conversely, with <tt>malloc()</tt>, the programmer has to specify 
  explicitly the number of bytes that have to be allocated. In addition, <tt>malloc()</tt> 
  returns a pointer to <tt>void</tt>, which has to be explicitly cast to the desired 
  type. This is both tedious and dangerous. Operator <tt>new</tt> returns a pointer 
  to the desired type, so no explicit type cast is required. For example</p>
<pre>
<tt>#include &lt;cstdlib&gt;</tt>
<tt>using namespace std;</tt>
<tt>void func()</tt>
<tt>{</tt>
<tt>  int * p = static_cast&lt;int *&gt; malloc(sizeof(int));</tt>
<tt>  int * p2 = new int;</tt>
<tt>}</tt>
<tt> </tt>
</pre>
<h3> <a name="Heading15"> Extensibility</a></h3>
<p>Operator <tt>new</tt> can be overloaded by a class. This feature enables specific 
  classes to use different memory management policies, as you will see next. On 
  the other hand, <tt>malloc()</tt> cannot be overloaded for a specific class.</p>
<p>The results of calling <tt>free()</tt> to release a pointer that was allocated 
  by <tt>new</tt>, or of using <tt>delete</tt> to release memory that was allocated 
  by <tt>malloc()</tt>, are undefined. The Standard does not guarantee that the 
  underlying implementation of operator <tt>new</tt> uses <tt>malloc()</tt>; furthermore, 
  on some implementations <tt>malloc()</tt> and <tt>new</tt> use different heaps.</p>
<h2> <a name="Heading16"> new and delete</a></h2>
<h3> <a name="Heading17"> Allocating and Deallocating Arrays Using new[] and delete[]</a></h3>
<p><tt>new[]</tt> allocates an array of objects of the specified type. The value 
  that is returned by <tt>new[]</tt> is the address of the first element in the 
  allocated array. For example</p>
<pre>
<tt>int main()</tt>
<tt>{</tt>
<tt>  int *p = new int[10];</tt>
<tt>  bool equal = (p == &amp;p[0]); //true</tt>
<tt>  delete[] p;</tt>
<tt>  return 0;</tt>
<tt>}</tt>
</pre>
<p>Objects that are allocated using <tt>new[]</tt> must be released by a call 
  to <tt>delete[]</tt>. Using plain <tt>delete</tt> instead of <tt>delete[]</tt> 
  in this case results in undefined behavior. This is because when <tt>new[]</tt> 
  is executed, the runtime system stores the number of elements in the allocated 
  array in an implementation-defined way. The corresponding <tt>delete[]</tt> 
  expression retrieves the number of allocated elements to invoke the same number 
  of destructors. How does <tt>new[]</tt> store the number of elements in the 
  allocated array? The most widely used technique is to allocate an extra <tt>sizeof(std::size_t)</tt> 
  bytes; that is, for a class <tt>C</tt>, the expression</p>
<pre>
<tt>C * p = new C[n];</tt>
</pre>
<p>allocates a memory buffer that contains <tt>sizeof(std::size_t) + n * sizeof 
  </tt> bytes. The value <tt>n</tt> is written to the allocated buffer just before 
  the first <tt>C</tt> object. When <tt>delete[]</tt> is invoked, it looks for 
  the value <tt>n</tt> in a fixed offset before <tt>p</tt> (which must point to 
  the first element in the array). <tt>delete[]</tt> then invokes <tt>C</tt>'s 
  destructor <tt>n</tt> times and, finally, releases the memory block. Plain <tt>delete</tt>, 
  on the other hand, does not perform such offset adjustments -- it simply invokes 
  the destructor of the object to which <tt>p</tt> points.</p>
<p>An alternative technique is to store <tt>n</tt> in an associative array in 
  which <tt>p</tt> serves as the key and <tt>n</tt> is its associated value. When 
  the statement</p>
<pre>
<tt>delete[] p;</tt>
</pre>
<p>is executed, <tt>delete[]</tt> can lookup <tt>p</tt> in an associative array 
  such as</p>
<pre>
<tt>std::map&lt;void *, std::size_t&gt;</tt>
</pre>
<p>and retrieve its associated value <tt>n</tt>. Other techniques for storing 
  the number of array elements can be used as well, but in any one of them, using 

⌨️ 快捷键说明

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