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

📄 ch02.htm

📁 c++语言操作手册
💻 HTM
📖 第 1 页 / 共 5 页
字号:
      block fixes this loophole. Following is an example of a function <tt>try</tt>       block:</p>    <pre><tt>class Err{}; </tt><tt>A::A(const string&amp; s) throw (Err);  //allowed to throw only </tt><tt>                                    //an exception of type Err</tt><tt>  try</tt><tt>    : str(s) //str's constructor might throw a bad_alloc </tt><tt>             //exception, which violates C's exception specification</tt><tt>    {</tt><tt>      // constructor function body</tt><tt>    }</tt><tt>    catch (...) //we get here when an exception is thrown</tt><tt>                //during the construction of str or C</tt><tt>    {</tt><tt>      throw Err(); //replace bad_alloc exception with an Err exception</tt><tt>    }</tt></pre>    <h3> <a name="Heading18">Memory Management</a></h3>    <p>The Standard now defines three different versions of operator <tt>new</tt>:       plain <tt>new</tt>, <tt>nothrow new</tt>, and placement <tt>new</tt>. Each       of these operators has an array version as well. The Standard also defines       six matching types of operator <tt>delete</tt> that correspond the specific       versions of <tt>new</tt>. Memory management and the recently added versions       of <tt>new</tt> and <tt>delete</tt> are discussed in further detail in Chapter       11, "Memory Management."</p>    <h4> Operator new Throws an Exception in Case of a Failure</h4>    <p>In earlier stages of C++, operator <tt>new</tt> returned a <tt>NULL</tt>       pointer when it failed to allocate the requested amount of memory. The C++       standardization committee changed the specification of operator <tt>new</tt>       so that it throws an exception of type <tt>std::bad_alloc</tt>, rather than       returning a <tt>NULL</tt> pointer, when it fails. A program that uses operator       <tt>new</tt> directly or indirectly has to handle a potential <tt>std::bad_alloc</tt>       exception. For example</p>    <pre><tt>void f(int size) //standard-conforming usage of operator new</tt><tt>{</tt><tt>  char *p = new char [size];</tt><tt>  //...use p safely</tt><tt>  delete [] p;</tt><tt>  return;</tt><tt>}</tt><tt>#include &lt;stdexcept&gt;</tt><tt>#include &lt;iostream&gt;</tt><tt>using namespace std;</tt><tt>const int BUF_SIZE = 1048576L;</tt><tt>int main()</tt><tt>{</tt><tt>  try</tt><tt>  {</tt><tt>    f(BUF_SIZE);</tt><tt>  }</tt><tt>  catch(bad_alloc&amp; ex)  //handle exception thrown from f()</tt><tt>  {</tt><tt>    cout&lt;&lt;ex.what()&lt;&lt;endl;</tt><tt>    //...other diagnostics and remedies</tt><tt>  }</tt><tt>  return -1;</tt><tt>}</tt></pre>    <h4> nothrow new</h4>    <p>The Standard also defines an exception-free version of operator <tt>new</tt>,       which returns a <tt>NULL</tt> pointer in case of a failure rather than throwing       an exception. This version of <tt>new</tt> takes an additional argument       named <tt>nothrow</tt>. For example</p>    <pre><tt>#include &lt;new&gt;</tt><tt>#include &lt;string&gt;</tt><tt>using namespace std;</tt><tt>void f(int size) // demonstrating nothrow new</tt><tt>{</tt><tt>  char *p = new (nothrow) char [size]; //array nothrow new</tt><tt>  if (p == 0)</tt><tt>  {</tt><tt>    //...use p</tt><tt>    delete [] p;</tt><tt>  }</tt><tt>  string *pstr = new (nothrow) string; //plain nothrow new</tt><tt>  if (pstr == 0)</tt><tt>  {</tt><tt>    //...use pstr</tt><tt>    delete [] pstr;</tt><tt>  }</tt><tt>  return;</tt><tt>}</tt></pre>    <h4> Placement new</h4>    <p>An additional version of operator <tt>new</tt> enables the user to construct       an object at a predetermined memory position. This version is called placement       <tt>new</tt>. Following is an example of using placement <tt>new</tt>:</p>    <pre><tt>#include &lt;new&gt;</tt><tt>#include &lt;iostream&gt;</tt><tt>using namespace std;</tt><tt>void placement()</tt><tt>{</tt><tt>  int   *pi = new int;     //plain new</tt><tt>  int   *p  = new (pi) int (5);  //placement new</tt><tt>  //...use p</tt><tt>  delete pi;</tt><tt>}</tt></pre>    <h3> <a name="Heading19">Constructors and Destructors</a></h3>    <p>Fundamental types can be initialized by a special constructor. In addition,       the Standard also defines a pseudo destructor for each of these types (see       Chapter 4, "Special Member Functions: Default Constructor, Copy Constructor,       Destructor, and Assignment Operator").</p>    <h4> Constructors of Fundamental Types</h4>    <p>Variables of fundamental types can be initialized by invoking their constructor       explicitly. For example</p>    <pre><tt>void f()</tt><tt>{</tt><tt>  int n = int(); // zero initialized</tt><tt>  char c = char(); // also zero initialized</tt><tt>  double d = double(0.5); //other initializers are allowed</tt><tt>}</tt></pre>    <p>This language extension enables uniform treatment in templates for fundamental       types and user-defined types.</p>    <h4> Explicit Constructors</h4>    <p>A constructor that takes a single argument is, by default, an implicit       conversion operator that converts its argument to an object of its class.       In order to avoid such implicit conversions, a constructor that takes one       argument can be declared <tt>explicit</tt>. For example</p>    <pre><tt>class C</tt><tt>{</tt><tt>public:</tt><tt>  explicit C(int size);  // disallow implicit conversion</tt><tt>};</tt></pre>    <h4> Pseudo Destructors</h4>    <p>A <i>pseudo destructor</i> is a syntactic construct whose sole purpose       is to satisfy the need for generic algorithms and containers. It is a no-op       code, and has no real effect on its object. For example</p>    <pre><tt>typedef int N;</tt><tt>void f()</tt><tt>{</tt><tt>  N i = 0;</tt><tt>  i.N::~N();  // pseudo destructor invocation</tt><tt>  i = 1;  // i  was not affected by the invocation of the pseudo destructor</tt><tt>}</tt></pre>    <h3> <a name="Heading20">Local Definitions and Scoping Rules</a></h3>    <p>The scoping rules for a variable that is defined in a <tt>for</tt> statement       were changed. Additionally, it is now possible to define and initialize       variables inside an <tt>if</tt> condition.</p>    <h4> The Scope of a Local Loop Counter</h4>    <p>C++ allows declaration of variables wherever they are needed, enabling       immediate initializations. A good example is a loop counter, which can be       declared inside a <tt>for</tt> statement. For example</p>    <pre><tt>void f()</tt><tt>{</tt><tt>  for (int i = 0; i &lt; 10; i++) // i declared and initialized </tt><tt>                               // inside a for-statement</tt><tt>  {</tt><tt>    cout &lt;&lt; i &lt;&lt;endl; //output 0 to 9</tt><tt>  }</tt><tt>  int n = i; //compilation error, i not in scope</tt><tt>}</tt></pre>    <p>In earlier stages of C++, a local variable declared in this way remained       accessible in its enclosing block. This was a source for bugs and name hiding.       Consequently, the standard has been revised to fix this loophole, so to       speak; local variables that are created this way are inaccessible outside       their <tt>for</tt> statement. In the preceding example, the variable <tt>i</tt>       goes out of scope when the loop is exited.</p>    <h4> Declaring Variables Inside an if Condition</h4>    <p>You can define and initialize a variable inside the condition of an <tt>if</tt>       statement. For example</p>    <pre><tt>class Base {/*..*/};</tt><tt>class Derived: public Base {/*..*/};</tt><tt>void func (Base&amp; b)</tt><tt>{</tt><tt>  if ( Derived *pd = dynamic_cast &lt; Derived* &gt; (&amp;b) ) //declaration </tt><tt>                                                      // inside an if-condition</tt><tt>  {</tt><tt>    //dynamic_cast was successful; use pd here</tt><tt>    return;</tt><tt>  }//pd goes out of scope at this point</tt><tt>  //otherwise dynamic_cast failed; variable pd is not in scope</tt><tt>}</tt></pre>    <p>The advantage of declaring the pointer <tt>pd</tt> locally is obvious:       It is always initialized with an appropriate value, and it isn't visible       to other parts of the program that are not to use it (see Chapter 12, "Optimizing       Your Code").</p>    <h3> <a name="Heading21">Namespaces</a></h3>    <p><i>Namespaces</i> were the latest feature to be added to the language.       Namespaces are used to prevent name conflicts and to facilitate configuration       management and version control in large-scale projects. Most of the components       of the Standard Library are grouped under namespace <tt>std</tt>. There       are three methods for injecting namespace members into a scope: a <tt>using</tt>       directive, a <tt>using</tt> declaration, or a fully qualified name. Argument-dependent       lookup, or Koenig lookup, simplifies the use of namespaces by automating       the name lookup process. Namespaces are discussed in more detail in Chapter       8, "Namespaces." </p>    <h3> <a name="Heading22">Templates</a></h3>    <p>A <i>template</i> is a mold from which related functions or classes are       instantiated. Templates have come a long way since they were first introduced       to the language in 1991. Back then, they were merely clever macros. However,       the adoption of STL required considerable extensions to this feature. An       overview of these extension is provided in the following sections. Templates       are discussed in detail in Chapter 9, "Templates."</p>    <h4> Template-Template Argument</h4>    <p>A template can now take a template as an argument. For example</p>    <pre><tt>int send(const std::vector&lt;char*&gt;&amp; );</tt><tt>int main()</tt><tt>{</tt><tt>  std::vector &lt;std::vector&lt;char*&gt; &gt; msg_que(10);</tt><tt>  //...fill msg_que</tt><tt>  for (int i =0; i &lt; 10; i++) //transmit messages</tt><tt>    send(msg_que[i]);</tt><tt>  return 0;</tt><tt>}</tt></pre>    <h4> Default Type Arguments</h4>    <p>Templates can have default type arguments. For example</p>    <pre><tt>template &lt;class T, class S = size_t &gt; class C  //using a default type</tt><tt>{/**/};</tt></pre>    <h4> Member Templates</h4>    <p>Templates can be nested; a template can be declared within another class       or a class template. Such a template is called a <i>member template</i>.       Following is an example:</p>    <pre><tt>template&lt;class T&gt; class C</tt><tt>{</tt><tt>public:</tt><tt>  template&lt;class T2&gt; int func(const T2&amp;); //declaration of a member template</tt><tt>  //...</tt><tt>};</tt><tt>template&lt;class T&gt; template&lt;class T2&gt; int C&lt;T&gt;::func(const T2&amp; s) // definition</tt><tt>{</tt><tt>   //...</tt><tt>}</tt></pre>    <h4> The typename Keyword</h4>    <p>To support member templates and template inheritance, the keyword <tt>typename</tt>       was added to the language. By default, the compiler assumes that a qualified       name refers to a non-type. The <tt>typename</tt> keyword instructs the compiler       to supersede this default interpretation and resolve the ambiguity in favor       of a typename instead.</p>    <h4> Exported Templates</h4>    <p>It is possible to compile a template definition only once, and to subsequently       use only the template's declaration in other translation units. To compile 

⌨️ 快捷键说明

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