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

📄 index.html

📁 C程序员手册(英文)
💻 HTML
📖 第 1 页 / 共 5 页
字号:
    <p>Unspecified behavior and implementation-defined behavior are consistent 
      -- albeit nonportable -- behaviors that are left intentionally unspecified 
      by the C++ Standard, usually to allow efficient and simple compiler implementation 
      on various platforms. Conversely, undefined behavior is always undesirable 
      and should never occur.</p>
    <h3> <a name="Heading11">The One Definition Rule</a></h3>
    <p>A class, an enumeration, an inline function with external linkage, a class 
      template, a nonstatic function template, a member function template, a static 
      data member of a class template, or a template specialization for which 
      some template parameters are not specified can be defined more than once 
      in a program -- provided that each definition appears in a different translation 
      unit, and provided that the definitions meet the requirements that are detailed 
      in the following sections.</p>
    <h4> Token-by-Token Identity</h4>
    <p>Each definition must contain the same sequence of tokens. For example</p>
    <pre>
<tt>  //file fisrt.cpp</tt>
<tt>inline int C::getVal () { return 5; }</tt>
<tt>  //file sec.cpp</tt>
<tt>typedef int I;</tt>
<tt>inline I C::getVal () { return 5; } // violation of ODR, </tt>
<tt>                                    // I and int are not identical tokens</tt>
</pre>
    <p>On the other hand, white spaces and comments are immaterial:</p>
    <pre>
<tt>  //file fisrt.cpp</tt>
<tt>inline int C::getVal () { return 5; }</tt>
<tt>  //file sec.cpp</tt>
<tt>inline int C::getVal () { /*complies with the ODR*/</tt>
<tt>return 5; }</tt>
</pre>
    <h4> Semantic Equivalence</h4>
    <p>Each token in the identical sequences of the separate definitions has the 
      same semantic contents. For example</p>
    <pre>
<tt>//file first.cpp</tt>
<tt>typedef int I;</tt>
<tt>inline I C::getVal () { return 5; }</tt>
<tt>//file second.cpp</tt>
<tt>typedef unsigned int I;</tt>
<tt>inline I C::getVal () { return 5; } //error; different semantic content for I</tt>
</pre>
    <h3> <a name="Heading12">Linkage Types</a></h3>
    <p>A name that refers to an object, reference, type, function, template, namespace, 
      or value that is declared in another scope is said to have <i>linkage</i>. 
      The linkage can be either <i>external </i>or <i>internal</i>. Otherwise, 
      the name has no linkage.</p>
    <h4> External Linkage</h4>
    <p>A name that can be referred to from other translation units or from other 
      scopes of the translation unit in which it was defined has <i>external linkage</i>. 
      Following are some examples:</p>
    <pre>
<tt>void g(int n) {} //g has external linkage</tt>
<tt>int glob; //glob has external linkage</tt>
<tt>extern const int E_MAX=1024; //E_MAX has external linkage</tt>
<tt>namespace N</tt>
<tt>{</tt>
<tt>  int num;  //N::num has external linkage</tt>
<tt>  void func();//N::func has external linkage</tt>
<tt>}</tt>
<tt>class C {}; //the name C has external linkage</tt>
</pre>
    <h4> Internal Linkage</h4>
    <p>A name that can be referred to by names from other scopes in the translation 
      unit in which it was declared, but not from other translation units, has 
      <i>internal linkage</i>. Following are some examples:</p>
    <pre>
<tt>static void func() {} //func has internal linkage</tt>
<tt>union //members of a non-local anonymous union have internal linkage</tt>
<tt>{</tt>
<tt>  int n;</tt>
<tt>  void *p;</tt>
<tt>};</tt>
<tt>const int MAX=1024; //non-extern const variables have internal linkage</tt>
<tt>typedef int I; //typedefs have internal linkage</tt>
</pre>
    <h4> Names With No Linkage</h4>
    <p>A name that can only be referred to from the scope in which it is declared 
      has no linkage. For example</p>
    <pre>
<tt>void f()</tt>
<tt>{</tt>
<tt>  int a; //a has no linkage</tt>
<tt>  class B {/**/}; //a local class has no linkage</tt>
<tt>}</tt>
</pre>
    <h3> <a name="Heading13">Side effect</a></h3>
    <p>A <i>side effect</i> is a change in the state of the execution environment. 
      Modifying an object, accessing a <tt>volatile</tt> object, invoking a library 
      I/O function, and calling a function that performs any of these operations 
      are all side effects.</p>
    <h2> <a name="Heading14">Addenda</a></h2>
    <p>This part details the new features -- and extensions to existing features 
      -- that have been adopted by the C++ Standard in recent years.</p>
    <h3> <a name="Heading15">New Typecast Operators</a></h3>
    <p>C++ still supports C-style cast, as in</p>
    <pre>
<tt>int i = (int) 7.333;</tt>
</pre>
    <p>Nonetheless, C-style cast notation is problematic for several reasons. 
      First, the operator <tt>()</tt> is already used excessively in the language: 
      in a function call, in precedence reordering of expressions, in operator 
      overloading, and in other syntactic constructs. Second, C-style cast carries 
      out different operations in different contexts -- so different that you 
      can hardly tell which is which. It can perform an innocuous standard cast, 
      such as converting an <tt>enum</tt> value to an <tt>int</tt>; but it can 
      also cast two nonrelated types to one another. In addition, a C-style cast 
      can be used to remove the <tt>const</tt> or <tt>volatile</tt> qualifiers 
      of an object (and in earlier stages of C++, the language was capable of 
      performing dynamic casts as well).</p>
    <p>Because of these multiple meanings, the C-style cast is opaque. Sometimes 
      it is very difficult for a reader to clearly understand the intent of the 
      code author who uses a C-style cast operation. Consider the following example:</p>
    <pre>
<tt>#include &lt;iostream&gt;</tt>
<tt>using namespace std;</tt>
<tt>void display(const unsigned char *pstr)</tt>
<tt>{</tt>
<tt>  cout&lt;&lt;pstr&lt;&lt;endl;</tt>
<tt>}</tt>
<tt>void func()</tt>
<tt>{</tt>
<tt>  const char * p = "a message";</tt>
<tt>  display( (unsigned char*) p); //signed to unsigned cast is required</tt>
<tt>                                // but const is also removed. was that</tt>
<tt>                                // intentional or a programmer's oversight?</tt>
<tt>}</tt>
</pre>
    <p>The new cast operators make the programmer's intention clearer and self-documenting. 
      In addition, they enable the compiler to detect mistakes that cannot be 
      detected with C-style cast. The new cast operators are intended to replace 
      C-style cast; C++ programmers are encouraged to use them instead of C-style 
      cast notation. These operators are detailed in the following sections.</p>
    <h4> static_cast</h4>
    <p><tt>static_cast</tt> &lt;<cite>Type</cite><tt>&gt; (</tt><cite>Expr</cite><tt>)</tt> 
      performs well-behaved and reasonably well-behaved casts. One of its uses 
      is to indicate explicitly a type conversion that is otherwise performed 
      implicitly by the compiler. </p>
    <p>For example</p>
    <pre>
<tt>class Base{};</tt>
<tt>class Derived : public Base {};</tt>
<tt>void func( Derived * pd)</tt>
<tt>{</tt>
<tt> Base * pb = static_cast&lt;Base *&gt; (pd); //explicit</tt>
<tt>}</tt>
</pre>
    <p>A pointer to a derived object can be automatically converted to a pointer 
      to a public base. The use of an explicit cast makes the programmer's intent 
      clearer.</p>
    <p><tt>static_cast</tt> can be used to document user-defined conversion. For 
      example</p>
    <pre>
<tt>class Integer</tt>
<tt>{</tt>
<tt>  public: operator int ();</tt>
<tt>};</tt>
<tt>void func(Integer&amp; integer)</tt>
<tt>{</tt>
<tt> int num = static_cast&lt;int&gt; (integer); //explicit</tt>
<tt>}</tt>
</pre>
    <p>Narrowing conversions of numeric types can also be performed explicitly 
      by a <tt>static_cast</tt>. For example</p>
    <pre>
<tt>void func()</tt>
<tt>{</tt>
<tt>  int num = 0;</tt>
<tt>  short short_num = static_cast&lt;short&gt; (num);</tt>
<tt>}</tt>
</pre>
    <p>This conversion is somewhat riskier than the previous conversions. A <tt>short</tt> 
      might not represent all the values that an <tt>int</tt> can hold; an explicit 
      cast is used here, instead of an implicit conversion, to indicate that a 
      type conversion is performed. Casting an integral value to an <tt>enum</tt> 
      is also a dangerous operation because there is no guarantee that the value 
      of an <tt>int</tt> can be represented in an <tt>enum</tt>. Note that in 
      this case, an explicit cast is necessary:</p>
    <pre>
<tt>void func()</tt>
<tt>{</tt>
<tt>  enum status {good, bad};</tt>
<tt>  int num = 0;</tt>
<tt>  status s = static_cast&lt;status&gt; (num);</tt>
<tt>}</tt>
</pre>
    <p>You can use <tt>static_cast</tt> to navigate through class hierarchies. 
      Unlike <tt>dynamic_cast</tt>, however, it relies solely on the information 
      that is available at compile time -- so don't use it instead of <tt>dynamic_cast</tt>. 
      Using <tt>static_cast</tt> for this purpose is safer than using C-style 
      cast because it does not perform conversions between nonrelated classes. 
      For example</p>
    <pre>
<tt>class A{};</tt>
<tt>class B{};</tt>
<tt>A *pa;</tt>
<tt>B * pb = static_cast&lt;B *&gt; (pa); //error, pointers are not related</tt>
</pre>
    <h4> const_cast</h4>
    <p><tt>const_cast &lt;T&gt; (Expr)</tt> removes only the <tt>const</tt> or 
      <tt>volatile</tt> qualifiers of <tt>Expr</tt> and converts them to type 
      <tt>T</tt>. <tt>T</tt> must be the same type of <tt>Expr</tt>, except for 
      the missing <tt>const</tt> or <tt>volatile</tt> attributes. For example</p>
    <pre>
<tt>#include &lt;iostream&gt;</tt>
<tt>using namespace std;</tt>
<tt>void print(char *p) //parameter should have been declared as const; alas,</tt>
<tt>{</tt>
<tt>  cout&lt;&lt;p;</tt>
<tt>}</tt>
<tt>void f()</tt>
<tt>{</tt>
<tt>  const char msg[] = "Hello World\n";</tt>
<tt>  char * p = const_cast&lt;char *&gt; (msg); //remove constness</tt>
<tt>  print(p);</tt>
<tt>}</tt>
</pre>
    <p><tt>const_cast</tt> can also convert an object to a <tt>const</tt> or <tt>volatile</tt> 
      one:</p>
    <pre>
<tt>void read(const volatile int * p);</tt>
<tt>int *p = new int;		 </tt>
<tt>read( const_cast&lt;const volatile int *&gt; (p) ); //explicit </tt>
</pre>
    <p>Note that the removal of the <tt>const</tt> qualifier of an object does 
      not guarantee that its value can be modified; it only guarantees that it 
      can be used in a context that requires a non-<tt>const</tt> object. So that 
      you understand these limitations, the following sections examines <tt>const</tt> 
      semantics in further detail.</p>
    <p><b>(f)<tt>const</tt> Semantics</b></p>
    <p>There are actually two types of <tt>const</tt>: <i>true</i> <tt>const</tt> 
      and <i>contractual</i> <tt>const</tt>. A true <tt>const</tt> object is an 
      lvalue that was originally defined as <tt>const</tt>. For example</p>
    <pre>
<tt>const int cn = 5; // true const</tt>
<tt>const std::string msg("press any key to continue"); // true const</tt>
</pre>
    <p>On the other hand, an object with contractual <tt>const</tt> quality is 
      one that was defined without the <tt>const</tt> qualifier, but that is treated 
      as though it were <tt>const</tt>. For example</p>
    <pre>
<tt>void ReadValue(const int&amp; num)</tt>
<tt>{</tt>
<tt>  cout&lt;&lt;num;  // num may not be modified in ReadValue()</tt>
<tt>}</tt>
<tt>int main()</tt>
<tt>{</tt>
<tt>  int n =0;</tt>
<tt>  ReadValue(n); //contractual const, n is treated as if it were const</tt>
<tt>}</tt>

⌨️ 快捷键说明

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