﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>C++博客-天蓝向上</title><link>http://www.cppblog.com/tianbianlan/</link><description /><language>zh-cn</language><lastBuildDate>Tue, 14 Apr 2026 08:02:37 GMT</lastBuildDate><pubDate>Tue, 14 Apr 2026 08:02:37 GMT</pubDate><ttl>60</ttl><item><title> Sequoiadb与spark对接步骤</title><link>http://www.cppblog.com/tianbianlan/archive/2015/05/26/210753.html</link><dc:creator>天边蓝</dc:creator><author>天边蓝</author><pubDate>Tue, 26 May 2015 09:13:00 GMT</pubDate><guid>http://www.cppblog.com/tianbianlan/archive/2015/05/26/210753.html</guid><wfw:comment>http://www.cppblog.com/tianbianlan/comments/210753.html</wfw:comment><comments>http://www.cppblog.com/tianbianlan/archive/2015/05/26/210753.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/tianbianlan/comments/commentRss/210753.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/tianbianlan/services/trackbacks/210753.html</trackback:ping><description><![CDATA[ 最近，完成了 Sequoiadb与spark的对接，为了方便以后查阅，记录如下~

版本说明：
Sequoiadb 版本: 1.12
spark版本：1.3.1

对接步骤：
1.配置hive-site.xml(hive要求，可省略)
<property>
        <name>hive.aux.jars.path</name>   
      <value>file:///ocsdev/hadoop/apache-hive-1.1.0-bin/lib/hive-sequoiadb-apache.jar,file:///ocsdev/hadoop/apache-hive-1.1.0-bin/lib/sequoiadb.jar</value>
        <description>Sequoiadb store handler jar file</description>
</property>


2.配置SPARK_CLASSPATH
export SPARK_CLASSPATH=/path/to/spark/lib/sequoiadb-driver-1.12.jar:/path/to/spark/lib/lib/spark-sequoiadb_2.10-1.12.jar:/ocsdev/hadoop/spark-1.3.1-bin-hadoop2.6/lib://path/to/spark/lib/mysql-connector-java-5.1.5-bin.jar

3.将sequoiadb-driver-1.12.jar、spark-sequoiadb_2.10-1.12.jar拷贝到spark的lib目录下；
4.hive-site.xml配置元数据存储方式
<property>
        <name>hive.metastore.local</name>
        <value>true</value>
    </property>
    <property>
        <name>javax.jdo.option.ConnectionURL</name>
        <value>jdbc:mysql://192.168.0.103:3306/hive?characterEncoding=UTF-8</value>
    </property>
    <property>
        <name>javax.jdo.option.ConnectionDriverName</name>
        <value>com.mysql.jdbc.Driver</value>
    </property>
    <property>
        <name>javax.jdo.option.ConnectionUserName</name>
        <value>hive</value>
    </property>
    <property>
        <name>javax.jdo.option.ConnectionPassword</name>
        <value>hive</value>
    </property>

5.创建Sequoiadb集合映射关系；
./spark_sql
>CREATE table lw_test_sdb (id int, r5 double) using com.sequoiadb.spark OPTIONS ( host '192.168.0.103:11810,192.168.0.104:11810,192.168.0.102:11810', collectionspace 'hj', collection 'aws_min',username '',password '');

6.查询数据
>select * from lw_test_sdb
NULL    0.0
23      23.4
12      34.5
Time taken: 0.825 seconds, Fetched 3 row(s)<img src ="http://www.cppblog.com/tianbianlan/aggbug/210753.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/tianbianlan/" target="_blank">天边蓝</a> 2015-05-26 17:13 <a href="http://www.cppblog.com/tianbianlan/archive/2015/05/26/210753.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title> RDD初探</title><link>http://www.cppblog.com/tianbianlan/archive/2015/04/18/210383.html</link><dc:creator>天边蓝</dc:creator><author>天边蓝</author><pubDate>Sat, 18 Apr 2015 14:16:00 GMT</pubDate><guid>http://www.cppblog.com/tianbianlan/archive/2015/04/18/210383.html</guid><wfw:comment>http://www.cppblog.com/tianbianlan/comments/210383.html</wfw:comment><comments>http://www.cppblog.com/tianbianlan/archive/2015/04/18/210383.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/tianbianlan/comments/commentRss/210383.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/tianbianlan/services/trackbacks/210383.html</trackback:ping><description><![CDATA[ RDD初探


RDD（resilient distributed dataset ）是Spark提出的一个创新性的概念，它提供了并行计算个阶段中数据的有效共享，弥补了MapReduce中的不足。与MapReduce单乏的Map和Reduce相比，在RDD上，Spark提供了丰富的操作，可以让程序开发人员利用RDD接口非常容易的编写出复杂的数据处理程序，先见见Spark版本的WordCount程序：

仅仅两行代码，相比MapReduce，是不是简洁了很多？


官网RDD的定义：
Spark revolves around the concept of a resilient distributed dataset (RDD), which is a fault-tolerant collection of elements that can be operated on in parallel. There are two ways to create RDDs: parallelizing an existing collection in your driver program, or referencing a dataset in an external storage system, such as a shared filesystem, HDFS, HBase, or any data source offering a Hadoop InputFormat.

RDD的特性：
1.分区的数据集
2.只读的数据集
3.只能从driver程序中已有的集合或外部存储进行创建
4.容错的，失败自动的快速重建

分区
分区，RDD是一个分区的数据集，其分区的多少决定着对这个RDD进行并行计算的粒度，在Spark中，每一个分区的计算在一个单独的任务中执行。对RDD的分区而言，用户可以指定其分区的数目；如果没有，系统将会使用默认值，默认情况下，其分区数为这个程序所分配到的资源的CPU核的数目；如，
指定分区数:

默认分区数：


位置优先
在Spark中，秉性着这么一种思想，&#8220;移动数据不如移动计算&#8221;，在Spark任务调度的时候，总是尽可能的将任务分配到数据块存储的位置。如，对HDFS文件生成的RDD，preferredLocation接口返回其每块数据所在的机器名或IP，在后续的任务调度中，调度器将尽可能的将计算任务分配到数据存储的位置，如：


RDD依赖关系
可以说，RDD依赖关系是Spark任务调度最根本的依据。
在RDD的转换过程中，每次转换都会生成一个新的RDD，在用户程序中，对于某个RDD往往会有一系列的复杂的转换，这样，就形成了一条类似流水线样的前后依赖关系。
在Spark中，存在两种类型的依赖，即窄依赖和宽依赖；
窄依赖：父RDD的每一个分区只被子RDD的一个分区所使用，如：map、filter等；
宽依赖：父RDD的每一个分区只被子RDD的多个分区所使用，如：groupbyKey等；

区分两种依赖的原因：
1.窄依赖可以在集群的一个节点上如流水一般的执行，无需物化很多无用的中间RDD，大大提升了计算性能；
2.窄依赖对于节点计算失败后的恢复会更加有效，只要重新计算其对应父RDD的相应分区即可；


RDD操作
RDD支持两种操作
Transformations：从一个已存的RDD生成一个新的RDD，如map操作
Action：执行一次计算并将相应的计算结果返回值driver程序，如reduce

在Spark中，所有的Transformation都是惰性的，他们只会记录其相应的依赖关系，而不会马上计算其结果，只有在action要求计算结果时才会实际计算RDD的值。
Spark提供了丰富的RDD操作，详细参考		http://spark.apache.org/docs/latest/api/scala/index.html#org.apache.spark.rdd.RDD

RDD的持久化
在Spark中，还有一个最重要的特性就是RDD的持久化。当你对一个RDD进行持久化操作时，spark会将该RDD的每个分区的第一次计算结果保存在相应的存储介质中。之后对该RDD的访问可以直接访问其存储的结果，这样我们可以将一些访问比较频繁的RDD进行持久化到内存中来，加快程序的处理时间（官网提供的数据时通常会加快速度10倍以上）
RDD的持久化通过persist() 和 cache() 方法实现；
<img src ="http://www.cppblog.com/tianbianlan/aggbug/210383.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/tianbianlan/" target="_blank">天边蓝</a> 2015-04-18 22:16 <a href="http://www.cppblog.com/tianbianlan/archive/2015/04/18/210383.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转]The Biggest Changes in C++11 </title><link>http://www.cppblog.com/tianbianlan/archive/2013/05/05/199992.html</link><dc:creator>天边蓝</dc:creator><author>天边蓝</author><pubDate>Sun, 05 May 2013 13:26:00 GMT</pubDate><guid>http://www.cppblog.com/tianbianlan/archive/2013/05/05/199992.html</guid><wfw:comment>http://www.cppblog.com/tianbianlan/comments/199992.html</wfw:comment><comments>http://www.cppblog.com/tianbianlan/archive/2013/05/05/199992.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/tianbianlan/comments/commentRss/199992.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/tianbianlan/services/trackbacks/199992.html</trackback:ping><description><![CDATA[http://coolshell.cn/articles/5265.html<br />
<p>源文章来自前C++标准委员会的&nbsp;<a href="http://www.softwarequalityconnection.com/author/dannykalev/">Danny Kalev</a>&nbsp;的&nbsp;<a href="http://www.softwarequalityconnection.com/2011/06/the-biggest-changes-in-c11-and-why-you-should-care/" target="_blank">The Biggest Changes in C++11 (and Why You Should Care)</a>，赖勇浩做了一个<a href="http://blog.csdn.net/lanphaday/article/details/6564162" target="_blank">中文翻译在这里</a>。所以，我就不翻译了，我在这里仅对文中提到的这些变化&#8220;<strong>追问为什么要引入这些变化</strong>&#8221;的一个探讨，<strong>只有知道为了什么，用在什么地方，我们才能真正学到这个知识</strong>。而以此你可以更深入地了解这些变化。所以，本文不是翻译。因为写得有些仓促，所以难免有问题，还请大家指正。</p>
<h4 class="color-programming"><a name="t0"></a>Lambda 表达式</h4>
<p>Lambda表达式来源于函数式编程，说白就了就是在使用的地方定义函数，有的语言叫&#8220;闭包&#8221;，如果 lambda 函数没有传回值(例如&nbsp;<tt>void</tt>&nbsp;)，其回返类型可被完全忽略。 定义在与 lambda 函数相同作用域的变量参考也可以被使用。这种的变量集合一般被称作 closure（闭包）。我在这里就不再讲这个事了。表达式的简单语法如下，</p>
<div>
<div id="highlighter_749642" class="syntaxhighlighter  cpp">
<table border="0" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td class="gutter">
<div class="line number1 index0 alt2">1</div></td>
<td class="code">
<div class="container">
<div class="line number1 index0 alt2"><code class="cpp plain">[capture](parameters)-&gt;return_type {body}</code></div></div></td></tr></tbody></table></div></div>
<p>原文的作者给出了下面的例子：</p>
<div>
<div id="highlighter_570026" class="syntaxhighlighter  cpp">
<table border="0" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td class="gutter">
<div class="line number1 index0 alt2">1</div>
<div class="line number2 index1 alt1">2</div>
<div class="line number3 index2 alt2">3</div>
<div class="line number4 index3 alt1">4</div>
<div class="line number5 index4 alt2">5</div>
<div class="line number6 index5 alt1">6</div>
<div class="line number7 index6 alt2">7</div>
<div class="line number8 index7 alt1">8</div>
<div class="line number9 index8 alt2">9</div>
<div class="line number10 index9 alt1">10</div></td>
<td class="code">
<div class="container">
<div class="line number1 index0 alt2"><code class="cpp color1 bold">int</code> <code class="cpp plain">main()</code></div>
<div class="line number2 index1 alt1"><code class="cpp plain">{</code></div>
<div class="line number3 index2 alt2"><code class="cpp spaces">&nbsp;&nbsp;&nbsp;</code><code class="cpp color1 bold">char</code> <code class="cpp plain">s[]=</code><code class="cpp string">"Hello World!"</code><code class="cpp plain">;</code></div>
<div class="line number4 index3 alt1"><code class="cpp spaces">&nbsp;&nbsp;&nbsp;</code><code class="cpp color1 bold">int</code> <code class="cpp plain">Uppercase = 0; </code><code class="cpp comments">//modified by the lambda</code></div>
<div class="line number5 index4 alt2"><code class="cpp spaces">&nbsp;&nbsp;&nbsp;</code><code class="cpp plain">for_each(s, s+</code><code class="cpp keyword bold">sizeof</code><code class="cpp plain">(s), [&amp;Uppercase] (</code><code class="cpp color1 bold">char</code> <code class="cpp plain">c) {</code></div>
<div class="line number6 index5 alt1"><code class="cpp spaces">&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="cpp keyword bold">if</code> <code class="cpp plain">(</code><code class="cpp functions bold">isupper</code><code class="cpp plain">(c))</code></div>
<div class="line number7 index6 alt2"><code class="cpp spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="cpp plain">Uppercase++;</code></div>
<div class="line number8 index7 alt1"><code class="cpp spaces">&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="cpp plain">});</code></div>
<div class="line number9 index8 alt2"><code class="cpp spaces">&nbsp;</code><code class="cpp plain">cout &lt;&lt; Uppercase &lt;&lt; </code><code class="cpp string">" uppercase letters in: "</code> <code class="cpp plain">&lt;&lt; s &lt;&lt;endl;</code></div>
<div class="line number10 index9 alt1"><code class="cpp plain">}</code></div></div></td></tr></tbody></table></div></div>
<p>在传统的STL中for_each() 这个玩意最后那个参数需要一个&#8220;函数对象&#8221;，所谓函数对象，其实是一个class，这个class重载了operator()，于是这个对象可以像函数的式样的使用。实现一个函数对象并不容易，需要使用template，比如下面这个例子就是函数对象的简单例子（实际的实现远比这个复杂）：</p>
<p><span id="more-5265"></span></p>
<div>
<div id="highlighter_676447" class="syntaxhighlighter  cpp">
<table border="0" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td class="gutter">
<div class="line number1 index0 alt2">1</div>
<div class="line number2 index1 alt1">2</div>
<div class="line number3 index2 alt2">3</div>
<div class="line number4 index3 alt1">4</div>
<div class="line number5 index4 alt2">5</div>
<div class="line number6 index5 alt1">6</div>
<div class="line number7 index6 alt2">7</div>
<div class="line number8 index7 alt1">8</div>
<div class="line number9 index8 alt2">9</div></td>
<td class="code">
<div class="container">
<div class="line number1 index0 alt2"><code class="cpp keyword bold">template</code> <code class="cpp plain">&lt;</code><code class="cpp keyword bold">class</code> <code class="cpp plain">T&gt;</code></div>
<div class="line number2 index1 alt1"><code class="cpp keyword bold">class</code> <code class="cpp plain">less</code></div>
<div class="line number3 index2 alt2"><code class="cpp plain">{</code></div>
<div class="line number4 index3 alt1"><code class="cpp keyword bold">public</code><code class="cpp plain">:</code></div>
<div class="line number5 index4 alt2"><code class="cpp spaces">&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="cpp color1 bold">bool</code> <code class="cpp plain">operator()(</code><code class="cpp keyword bold">const</code> <code class="cpp plain">T&amp;l, </code><code class="cpp keyword bold">const</code> <code class="cpp plain">T&amp;r)</code><code class="cpp keyword bold">const</code></div>
<div class="line number6 index5 alt1"><code class="cpp spaces">&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="cpp plain">{</code></div>
<div class="line number7 index6 alt2"><code class="cpp spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="cpp keyword bold">return</code> <code class="cpp plain">l &lt; r;</code></div>
<div class="line number8 index7 alt1"><code class="cpp spaces">&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="cpp plain">}</code></div>
<div class="line number9 index8 alt2"><code class="cpp plain">};</code></div></div></td></tr></tbody></table></div></div>
<p class="color-programming">所以，<strong>C++引入Lambda的最主要原因就是1）可以定义匿名函数，2）编译器会把其转成函数对象</strong>。相信你会和我一样，会疑问为什么以前STL中的ptr_fun()这个函数对象不能用？（ptr_fun()就是把一个自然函数转成函数对象的）。原因是，ptr_fun() 的局限是其接收的自然函数只能有1或2个参数。</p>
<p class="color-programming">那么，除了方便外，为什么一定要使用Lambda呢？它比传统的函数或是函数对象有什么好处呢？我个人所理解的是，这种函数之年以叫&#8220;闭包&#8221;，就是因为其限制了别人的访问，更私有。也可以认为他是一次性的方法。Lambda表达式应该是简洁的，极私有的，为了更易的代码和更方便的编程。</p>
<h4 class="color-programming"><a name="t1"></a>自动类型推导 auto</h4>
<p>在这一节中，原文主要介绍了两个关键字 auto 和 deltype，示例如下：</p>
<div>
<div id="highlighter_404721" class="syntaxhighlighter  cpp">
<table border="0" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td class="gutter">
<div class="line number1 index0 alt2">1</div>
<div class="line number2 index1 alt1">2</div>
<div class="line number3 index2 alt2">3</div>
<div class="line number4 index3 alt1">4</div></td>
<td class="code">
<div class="container">
<div class="line number1 index0 alt2"><code class="cpp plain">auto x=0; </code><code class="cpp comments">//x has type int because 0 is int</code></div>
<div class="line number2 index1 alt1"><code class="cpp plain">auto c=</code><code class="cpp string">'a'</code><code class="cpp plain">; </code><code class="cpp comments">//char</code></div>
<div class="line number3 index2 alt2"><code class="cpp plain">auto d=0.5; </code><code class="cpp comments">//double</code></div>
<div class="line number4 index3 alt1"><code class="cpp plain">auto national_debt=14400000000000LL;</code><code class="cpp comments">//long long</code></div></div></td></tr></tbody></table></div></div>
<p>auto 最大的好处就是让代码简洁，尤其是那些模板类的声明，比如：STL中的容器的迭代子类型。</p>
<div>
<div id="highlighter_275794" class="syntaxhighlighter  cpp">
<table border="0" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td class="gutter">
<div class="line number1 index0 alt2">1</div></td>
<td class="code">
<div class="container">
<div class="line number1 index0 alt2"><code class="cpp plain">vector&lt;</code><code class="cpp color1 bold">int</code><code class="cpp plain">&gt;::const_iterator ci = vi.begin();</code></div></div></td></tr></tbody></table></div></div>
<p>可以变成：</p>
<div>
<div id="highlighter_372866" class="syntaxhighlighter  cpp">
<table border="0" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td class="gutter">
<div class="line number1 index0 alt2">1</div></td>
<td class="code">
<div class="container">
<div class="line number1 index0 alt2"><code class="cpp plain">auto ci = vi.begin();</code></div></div></td></tr></tbody></table></div></div>
<p>模板这个特性让C++的代码变得很难读，不信你可以看看STL的源码，那是一个乱啊。使用auto必需一个初始化值，编译器可以通过这个初始化值推导出类型。因为auto是来简化模板类引入的代码难读的问题，如上面的示例，iteration这种类型就最适合用auto的，但是，我们不应该把其滥用。</p>
<p>比如下面的代码的可读性就降低了。因为，我不知道ProcessData返回什么？int? bool? 还是对象？或是别的什么？这让你后面的程序不知道怎么做。</p>
<div>
<div id="highlighter_652563" class="syntaxhighlighter  cpp">
<table border="0" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td class="gutter">
<div class="line number1 index0 alt2">1</div></td>
<td class="code">
<div class="container">
<div class="line number1 index0 alt2"><code class="cpp plain">auto obj = ProcessData(someVariables);</code></div></div></td></tr></tbody></table></div></div>
<p>但是下面的程序就没有问题，因为pObject的型别在后面的new中有了。</p>
<div>
<div id="highlighter_665966" class="syntaxhighlighter  cpp">
<table border="0" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td class="gutter">
<div class="line number1 index0 alt2">1</div></td>
<td class="code">
<div class="container">
<div class="line number1 index0 alt2"><code class="cpp plain">auto pObject = </code><code class="cpp keyword bold">new</code> <code class="cpp plain">SomeType&lt;OtherType&gt;::SomeOtherType();</code></div></div></td></tr></tbody></table></div></div>
<h4><a name="t2"></a>自动化推导 decltype</h4>
<p>关于&nbsp;<code>decltype</code>&nbsp;是一个操作符，其可以评估括号内表达式的类型，其规则如下：</p>
<ol><li>如果表达式e是一个变量，那么就是这个变量的类型。</li><li>如果表达式e是一个函数，那么就是这个函数返回值的类型。</li><li>如果不符合1和2，如果e是左值，类型为T，那么decltype(e)是T&amp;；如果是右值，则是T。</li></ol>
<p>原文给出的示例如下，我们可以看到，这个让的确我们的定义变量省了很多事。</p>
<div>
<div id="highlighter_595885" class="syntaxhighlighter  cpp">
<table border="0" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td class="gutter">
<div class="line number1 index0 alt2">1</div>
<div class="line number2 index1 alt1">2</div>
<div class="line number3 index2 alt2">3</div></td>
<td class="code">
<div class="container">
<div class="line number1 index0 alt2"><code class="cpp keyword bold">const</code> <code class="cpp plain">vector&lt;</code><code class="cpp color1 bold">int</code><code class="cpp plain">&gt; vi;</code></div>
<div class="line number2 index1 alt1"><code class="cpp keyword bold">typedef</code> <code class="cpp plain">decltype (vi.begin()) CIT;</code></div>
<div class="line number3 index2 alt2"><code class="cpp plain">CIT another_const_iterator;</code></div></div></td></tr></tbody></table></div></div>
<p>还有一个适合的用法是用来typedef函数指针，也会省很多事。比如：</p>
<div>
<div id="highlighter_651396" class="syntaxhighlighter  cpp">
<table border="0" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td class="gutter">
<div class="line number1 index0 alt2">1</div>
<div class="line number2 index1 alt1">2</div>
<div class="line number3 index2 alt2">3</div></td>
<td class="code">
<div class="container">
<div class="line number1 index0 alt2"><code class="cpp plain">decltype(&amp;myfunc) pfunc = 0;</code></div>
<div class="line number2 index1 alt1">&nbsp;</div>
<div class="line number3 index2 alt2"><code class="cpp keyword bold">typedef</code> <code class="cpp plain">decltype(&amp;A::func1) type;</code></div></div></td></tr></tbody></table></div></div>
<h4><a name="t3"></a>auto 和 decltype 的差别和关系</h4>
<p><a href="http://en.wikipedia.org/wiki/C%2B%2B0x#Type_inference" rel="nofollow" target="_blank">Wikipedia 上是这么说的</a>（关于decltype的规则见上）</p>
<div>
<div id="highlighter_153422" class="syntaxhighlighter  cpp">
<table border="0" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td class="gutter">
<div class="line number1 index0 alt2">1</div>
<div class="line number2 index1 alt1">2</div>
<div class="line number3 index2 alt2">3</div>
<div class="line number4 index3 alt1">4</div>
<div class="line number5 index4 alt2">5</div>
<div class="line number6 index5 alt1">6</div>
<div class="line number7 index6 alt2">7</div>
<div class="line number8 index7 alt1">8</div>
<div class="line number9 index8 alt2">9</div>
<div class="line number10 index9 alt1">10</div>
<div class="line number11 index10 alt2">11</div>
<div class="line number12 index11 alt1">12</div>
<div class="line number13 index12 alt2">13</div>
<div class="line number14 index13 alt1">14</div></td>
<td class="code">
<div class="container">
<div class="line number1 index0 alt2"><code class="cpp preprocessor">#include &lt;vector&gt;</code></div>
<div class="line number2 index1 alt1">&nbsp;</div>
<div class="line number3 index2 alt2"><code class="cpp color1 bold">int</code> <code class="cpp plain">main()</code></div>
<div class="line number4 index3 alt1"><code class="cpp plain">{</code></div>
<div class="line number5 index4 alt2"><code class="cpp spaces">&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="cpp keyword bold">const</code> <code class="cpp plain">std::vector&lt;</code><code class="cpp color1 bold">int</code><code class="cpp plain">&gt; v(1);</code></div>
<div class="line number6 index5 alt1"><code class="cpp spaces">&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="cpp plain">auto a = v[0];&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </code><code class="cpp comments">// a 的类型是 int</code></div>
<div class="line number7 index6 alt2"><code class="cpp spaces">&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="cpp plain">decltype(v[0]) b = 1; </code><code class="cpp comments">// b 的类型是 const int&amp;, 因为函数的返回类型是</code></div>
<div class="line number8 index7 alt1"><code class="cpp spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="cpp comments">// std::vector&lt;int&gt;::operator[](size_type) const</code></div>
<div class="line number9 index8 alt2"><code class="cpp spaces">&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="cpp plain">auto c = 0;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </code><code class="cpp comments">// c 的类型是 int</code></div>
<div class="line number10 index9 alt1"><code class="cpp spaces">&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="cpp plain">auto d = c;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </code><code class="cpp comments">// d 的类型是 int</code></div>
<div class="line number11 index10 alt2"><code class="cpp spaces">&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="cpp plain">decltype(c) e;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </code><code class="cpp comments">// e 的类型是 int, 因为 c 的类型是int</code></div>
<div class="line number12 index11 alt1"><code class="cpp spaces">&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="cpp plain">decltype((c)) f = c;&nbsp; </code><code class="cpp comments">// f 的类型是 int&amp;, 因为 (c) 是左值</code></div>
<div class="line number13 index12 alt2"><code class="cpp spaces">&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="cpp plain">decltype(0) g;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </code><code class="cpp comments">// g 的类型是 int, 因为 0 是右值</code></div>
<div class="line number14 index13 alt1"><code class="cpp plain">}</code></div></div></td></tr></tbody></table></div></div>
<p>如果auto 和 decltype 在一起使用会是什么样子？能看下面的示例，下面这个示例也是引入decltype的一个原因&#8212;&#8212;让C++有能力写一个 &#8220; <a title="Wrapper function" href="http://en.wikipedia.org/wiki/Wrapper_function">forwarding function</a>&nbsp;模板&#8221;，</p>
<div>
<div id="highlighter_45354" class="syntaxhighlighter  cpp">
<table border="0" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td class="gutter">
<div class="line number1 index0 alt2">1</div>
<div class="line number2 index1 alt1">2</div>
<div class="line number3 index2 alt2">3</div></td>
<td class="code">
<div class="container">
<div class="line number1 index0 alt2"><code class="cpp keyword bold">template</code><code class="cpp plain">&lt; </code><code class="cpp keyword bold">typename</code> <code class="cpp plain">LHS, </code><code class="cpp keyword bold">typename</code> <code class="cpp plain">RHS&gt;</code></div>
<div class="line number2 index1 alt1"><code class="cpp spaces">&nbsp;&nbsp;</code><code class="cpp plain">auto AddingFunc(</code><code class="cpp keyword bold">const</code> <code class="cpp plain">LHS &amp;lhs, </code><code class="cpp keyword bold">const</code> <code class="cpp plain">RHS &amp;rhs) -&gt; decltype(lhs+rhs)</code></div>
<div class="line number3 index2 alt2"><code class="cpp plain">{</code><code class="cpp keyword bold">return</code> <code class="cpp plain">lhs + rhs;}</code></div></div></td></tr></tbody></table></div></div>
<p>这个函数模板看起来相当费解，其用到了auto 和 decltype 来扩展了已有的模板技术的不足。怎么个不足呢？在上例中，我不知道AddingFunc会接收什么样类型的对象，这两个对象的 + 操作符返回的类型也不知道，老的模板函数无法定义AddingFunc返回值和这两个对象相加后的返回值匹配，所以，你可以使用上述的这种定义。</p>
<h4 class="color-programming"><a name="t4"></a>统一的初始化语法</h4>
<p>C/C++的初始化的方法比较，C++ 11 用大括号统一了这些初始化的方法。</p>
<p>比如：POD的类型。</p>
<div>
<div id="highlighter_178137" class="syntaxhighlighter  cpp">
<table border="0" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td class="gutter">
<div class="line number1 index0 alt2">1</div>
<div class="line number2 index1 alt1">2</div></td>
<td class="code">
<div class="container">
<div class="line number1 index0 alt2"><code class="cpp color1 bold">int</code> <code class="cpp plain">arr[4]={0,1,2,3};</code></div>
<div class="line number2 index1 alt1"><code class="cpp keyword bold">struct</code> <code class="cpp color1 bold">tm</code> <code class="cpp plain">today={0};</code></div></div></td></tr></tbody></table></div></div>
<p>关于POD相说两句，所谓POD就是<a href="http://en.wikipedia.org/wiki/Plain_Old_Data_Structures" target="_blank">Plain Old Data</a>，当class/struct是<em>极简的(trivial)</em>、属于<em>标准布局(standard-layout)</em>，以及他的所有非静态（non-static）成员都是POD时，会被视为POD。如：</p>
<div>
<div id="highlighter_451730" class="syntaxhighlighter  cpp">
<table border="0" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td class="gutter">
<div class="line number1 index0 alt2">1</div>
<div class="line number2 index1 alt1">2</div>
<div class="line number3 index2 alt2">3</div></td>
<td class="code">
<div class="container">
<div class="line number1 index0 alt2"><code class="cpp keyword bold">struct</code> <code class="cpp plain">A { </code><code class="cpp color1 bold">int</code> <code class="cpp plain">m; }; </code><code class="cpp comments">// POD</code></div>
<div class="line number2 index1 alt1"><code class="cpp keyword bold">struct</code> <code class="cpp plain">B { ~B(); </code><code class="cpp color1 bold">int</code> <code class="cpp plain">m; }; </code><code class="cpp comments">// non-POD, compiler generated default ctor</code></div>
<div class="line number3 index2 alt2"><code class="cpp keyword bold">struct</code> <code class="cpp plain">C { C() : m() {}; ~C(); </code><code class="cpp color1 bold">int</code> <code class="cpp plain">m; }; </code><code class="cpp comments">// non-POD, default-initialising m</code></div></div></td></tr></tbody></table></div></div>
<p>POD的初始化有点怪，比如上例，new A; 和new A(); 是不一样的，对于其内部的m，前者没有被初始化，后者被初始化了（不同 的编译器行为不一样，VC++和GCC不一样）。而非POD的初始化，则都会被初始化。</p>
<p>从这点可以看出，C/C++的初始化问题很奇怪，所以，在C++ 2011版中就做了统一。原文作者给出了如下的示例：</p>
<div>
<div id="highlighter_506998" class="syntaxhighlighter  cpp">
<table border="0" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td class="gutter">
<div class="line number1 index0 alt2">1</div>
<div class="line number2 index1 alt1">2</div>
<div class="line number3 index2 alt2">3</div>
<div class="line number4 index3 alt1">4</div>
<div class="line number5 index4 alt2">5</div>
<div class="line number6 index5 alt1">6</div>
<div class="line number7 index6 alt2">7</div>
<div class="line number8 index7 alt1">8</div>
<div class="line number9 index8 alt2">9</div></td>
<td class="code">
<div class="container">
<div class="line number1 index0 alt2"><code class="cpp plain">C c {0,0}; </code><code class="cpp comments">//C++11 only. 相当于: C c(0,0);</code></div>
<div class="line number2 index1 alt1">&nbsp;</div>
<div class="line number3 index2 alt2"><code class="cpp color1 bold">int</code><code class="cpp plain">* a = </code><code class="cpp keyword bold">new</code> <code class="cpp color1 bold">int</code><code class="cpp plain">[3] { 1, 2, 0 }; /C++11 only</code></div>
<div class="line number4 index3 alt1">&nbsp;</div>
<div class="line number5 index4 alt2"><code class="cpp keyword bold">class</code> <code class="cpp plain">X {</code></div>
<div class="line number6 index5 alt1"><code class="cpp spaces">&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="cpp color1 bold">int</code> <code class="cpp plain">a[4];</code></div>
<div class="line number7 index6 alt2"><code class="cpp spaces">&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="cpp keyword bold">public</code><code class="cpp plain">:</code></div>
<div class="line number8 index7 alt1"><code class="cpp spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="cpp plain">X() : a{1,2,3,4} {} </code><code class="cpp comments">//C++11, member array initializer</code></div>
<div class="line number9 index8 alt2"><code class="cpp plain">};</code></div></div></td></tr></tbody></table></div></div>
<p>容器的初始化：</p>
<div>
<div id="highlighter_261648" class="syntaxhighlighter  cpp">
<table border="0" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td class="gutter">
<div class="line number1 index0 alt2">1</div>
<div class="line number2 index1 alt1">2</div>
<div class="line number3 index2 alt2">3</div>
<div class="line number4 index3 alt1">4</div>
<div class="line number5 index4 alt2">5</div></td>
<td class="code">
<div class="container">
<div class="line number1 index0 alt2"><code class="cpp comments">// C++11 container initializer</code></div>
<div class="line number2 index1 alt1"><code class="cpp plain">vector&lt;string&gt; vs={ </code><code class="cpp string">"first"</code><code class="cpp plain">, </code><code class="cpp string">"second"</code><code class="cpp plain">, </code><code class="cpp string">"third"</code><code class="cpp plain">};</code></div>
<div class="line number3 index2 alt2"><code class="cpp plain">map singers =</code></div>
<div class="line number4 index3 alt1"><code class="cpp plain">{ {</code><code class="cpp string">"Lady Gaga"</code><code class="cpp plain">, </code><code class="cpp string">"+1 (212) 555-7890"</code><code class="cpp plain">},</code></div>
<div class="line number5 index4 alt2"><code class="cpp plain">{</code><code class="cpp string">"Beyonce Knowles"</code><code class="cpp plain">, </code><code class="cpp string">"+1 (212) 555-0987"</code><code class="cpp plain">}};</code></div></div></td></tr></tbody></table></div></div>
<p>还支持像Java一样的成员初始化：</p>
<div>
<div id="highlighter_296330" class="syntaxhighlighter  cpp">
<table border="0" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td class="gutter">
<div class="line number1 index0 alt2">1</div>
<div class="line number2 index1 alt1">2</div>
<div class="line number3 index2 alt2">3</div>
<div class="line number4 index3 alt1">4</div>
<div class="line number5 index4 alt2">5</div>
<div class="line number6 index5 alt1">6</div></td>
<td class="code">
<div class="container">
<div class="line number1 index0 alt2"><code class="cpp keyword bold">class</code> <code class="cpp plain">C</code></div>
<div class="line number2 index1 alt1"><code class="cpp plain">{</code></div>
<div class="line number3 index2 alt2"><code class="cpp spaces">&nbsp;&nbsp;&nbsp;</code><code class="cpp color1 bold">int</code> <code class="cpp plain">a=7; </code><code class="cpp comments">//C++11 only</code></div>
<div class="line number4 index3 alt1"><code class="cpp spaces">&nbsp;</code><code class="cpp keyword bold">public</code><code class="cpp plain">:</code></div>
<div class="line number5 index4 alt2"><code class="cpp spaces">&nbsp;&nbsp;&nbsp;</code><code class="cpp plain">C();</code></div>
<div class="line number6 index5 alt1"><code class="cpp plain">};</code></div></div></td></tr></tbody></table></div></div>
<h4 class="color-programming"><a name="t5"></a>Delete 和 Default 函数</h4>
<p>我们知道C++的编译器在你没有定义某些成员函数的时候会给你的类自动生成这些函数，比如，构造函数，拷贝构造，析构函数，赋值函数。有些时候，我们不想要这些函数，比如，构造函数，因为我们想做实现单例模式。传统的做法是将其声明成private类型。</p>
<p>在新的C++中引入了两个指示符，delete意为告诉编译器不自动产生这个函数，default告诉编译器产生一个默认的。原文给出了下面两个例子：</p>
<div>
<div id="highlighter_727542" class="syntaxhighlighter  cpp">
<table border="0" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td class="gutter">
<div class="line number1 index0 alt2">1</div>
<div class="line number2 index1 alt1">2</div>
<div class="line number3 index2 alt2">3</div>
<div class="line number4 index3 alt1">4</div>
<div class="line number5 index4 alt2">5</div></td>
<td class="code">
<div class="container">
<div class="line number1 index0 alt2"><code class="cpp keyword bold">struct</code> <code class="cpp plain">A</code></div>
<div class="line number2 index1 alt1"><code class="cpp plain">{</code></div>
<div class="line number3 index2 alt2"><code class="cpp spaces">&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="cpp plain">A()=</code><code class="cpp keyword bold">default</code><code class="cpp plain">; </code><code class="cpp comments">//C++11</code></div>
<div class="line number4 index3 alt1"><code class="cpp spaces">&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="cpp keyword bold">virtual</code> <code class="cpp plain">~A()=</code><code class="cpp keyword bold">default</code><code class="cpp plain">; </code><code class="cpp comments">//C++11</code></div>
<div class="line number5 index4 alt2"><code class="cpp plain">};</code></div></div></td></tr></tbody></table></div></div>
<p>再如delete</p>
<div>
<div id="highlighter_968982" class="syntaxhighlighter  cpp">
<table border="0" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td class="gutter">
<div class="line number1 index0 alt2">1</div>
<div class="line number2 index1 alt1">2</div>
<div class="line number3 index2 alt2">3</div>
<div class="line number4 index3 alt1">4</div>
<div class="line number5 index4 alt2">5</div>
<div class="line number6 index5 alt1">6</div>
<div class="line number7 index6 alt2">7</div></td>
<td class="code">
<div class="container">
<div class="line number1 index0 alt2"><code class="cpp keyword bold">struct</code> <code class="cpp plain">NoCopy</code></div>
<div class="line number2 index1 alt1"><code class="cpp plain">{</code></div>
<div class="line number3 index2 alt2"><code class="cpp spaces">&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="cpp plain">NoCopy &amp; operator =( </code><code class="cpp keyword bold">const</code> <code class="cpp plain">NoCopy &amp; ) = </code><code class="cpp keyword bold">delete</code><code class="cpp plain">;</code></div>
<div class="line number4 index3 alt1"><code class="cpp spaces">&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="cpp plain">NoCopy ( </code><code class="cpp keyword bold">const</code> <code class="cpp plain">NoCopy &amp; ) = </code><code class="cpp keyword bold">delete</code><code class="cpp plain">;</code></div>
<div class="line number5 index4 alt2"><code class="cpp plain">};</code></div>
<div class="line number6 index5 alt1"><code class="cpp plain">NoCopy a;</code></div>
<div class="line number7 index6 alt2"><code class="cpp plain">NoCopy b(a); </code><code class="cpp comments">//compilation error, copy ctor is deleted</code></div></div></td></tr></tbody></table></div></div>
<p>这里，我想说一下，为什么我们需要default？我什么都不写不就是default吗？不全然是，比如构造函数，因为只要你定义了一个构造函数，编译器就不会给你生成一个默认的了。所以，为了要让默认的和自定义的共存，才引入这个参数，如下例所示：</p>
<div>
<div id="highlighter_726892" class="syntaxhighlighter  cpp">
<table border="0" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td class="gutter">
<div class="line number1 index0 alt2">1</div>
<div class="line number2 index1 alt1">2</div>
<div class="line number3 index2 alt2">3</div>
<div class="line number4 index3 alt1">4</div>
<div class="line number5 index4 alt2">5</div></td>
<td class="code">
<div class="container">
<div class="line number1 index0 alt2"><code class="cpp keyword bold">struct</code> <code class="cpp plain">SomeType</code></div>
<div class="line number2 index1 alt1"><code class="cpp plain">{</code></div>
<div class="line number3 index2 alt2"><code class="cpp spaces">&nbsp;</code><code class="cpp plain">SomeType() = </code><code class="cpp keyword bold">default</code><code class="cpp plain">; </code><code class="cpp comments">// 使用编译器生成的默认构造函数</code></div>
<div class="line number4 index3 alt1"><code class="cpp spaces">&nbsp;</code><code class="cpp plain">SomeType(OtherType value);</code></div>
<div class="line number5 index4 alt2"><code class="cpp plain">};</code></div></div></td></tr></tbody></table></div></div>
<p>关于delete还有两个有用的地方是</p>
<p>1）让你的对象只能生成在栈内存上：</p>
<div>
<div id="highlighter_64998" class="syntaxhighlighter  cpp">
<table border="0" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td class="gutter">
<div class="line number1 index0 alt2">1</div>
<div class="line number2 index1 alt1">2</div>
<div class="line number3 index2 alt2">3</div></td>
<td class="code">
<div class="container">
<div class="line number1 index0 alt2"><code class="cpp keyword bold">struct</code> <code class="cpp plain">NonNewable {</code></div>
<div class="line number2 index1 alt1"><code class="cpp spaces">&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="cpp keyword bold">void</code> <code class="cpp plain">*operator </code><code class="cpp keyword bold">new</code><code class="cpp plain">(std::</code><code class="cpp color1 bold">size_t</code><code class="cpp plain">) = </code><code class="cpp keyword bold">delete</code><code class="cpp plain">;</code></div>
<div class="line number3 index2 alt2"><code class="cpp plain">};</code></div></div></td></tr></tbody></table></div></div>
<p>2）阻止函数的其形参的类型调用：（若尝试以 double 的形参调用&nbsp;<code>f()</code>，将会引发编译期错误， 编译器不会自动将 double 形参转型为 int 再调用<code>f()</code>，如果传入的参数是double，则会出现编译错误）</p>
<div>
<div id="highlighter_100259" class="syntaxhighlighter  cpp">
<table border="0" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td class="gutter">
<div class="line number1 index0 alt2">1</div>
<div class="line number2 index1 alt1">2</div></td>
<td class="code">
<div class="container">
<div class="line number1 index0 alt2"><code class="cpp keyword bold">void</code> <code class="cpp plain">f(</code><code class="cpp color1 bold">int</code> <code class="cpp plain">i);</code></div>
<div class="line number2 index1 alt1"><code class="cpp spaces">&nbsp;</code><code class="cpp keyword bold">void</code> <code class="cpp plain">f(</code><code class="cpp color1 bold">double</code><code class="cpp plain">) = </code><code class="cpp keyword bold">delete</code><code class="cpp plain">;</code></div></div></td></tr></tbody></table></div></div>
<h4 class="color-programming"><a name="t6"></a>nullptr</h4>
<p>C/C++的NULL宏是个被有很多潜在BUG的宏。因为有的库把其定义成整数0，有的定义成 (void*)0。在C的时代还好。但是在C++的时代，这就会引发很多问题。你可以上网看看。这是为什么需要&nbsp;<code>nullptr</code>&nbsp;的原因。&nbsp;<code>nullptr</code>&nbsp;是强类型的。</p>
<div>
<div id="highlighter_74048" class="syntaxhighlighter  cpp">
<table border="0" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td class="gutter">
<div class="line number1 index0 alt2">1</div>
<div class="line number2 index1 alt1">2</div>
<div class="line number3 index2 alt2">3</div>
<div class="line number4 index3 alt1">4</div>
<div class="line number5 index4 alt2">5</div>
<div class="line number6 index5 alt1">6</div></td>
<td class="code">
<div class="container">
<div class="line number1 index0 alt2"><code class="cpp keyword bold">void</code> <code class="cpp plain">f(</code><code class="cpp color1 bold">int</code><code class="cpp plain">); </code><code class="cpp comments">//#1</code></div>
<div class="line number2 index1 alt1"><code class="cpp keyword bold">void</code> <code class="cpp plain">f(</code><code class="cpp color1 bold">char</code> <code class="cpp plain">*);</code><code class="cpp comments">//#2</code></div>
<div class="line number3 index2 alt2"><code class="cpp comments">//C++03</code></div>
<div class="line number4 index3 alt1"><code class="cpp plain">f(0); </code><code class="cpp comments">//二义性</code></div>
<div class="line number5 index4 alt2"><code class="cpp comments">//C++11</code></div>
<div class="line number6 index5 alt1"><code class="cpp plain">f(nullptr) </code><code class="cpp comments">//无二义性，调用f(char*)</code></div></div></td></tr></tbody></table></div></div>
<p><code>所以在新版中请以 nullptr</code> 初始化指针。</p>
<h4 class="color-programming"><a name="t7"></a>委托构造</h4>
<p>在以前的C++中，构造函数之间不能互相调用，所以，我们在写这些相似的构造函数里，我们会把相同的代码放到一个私有的成员函数中。</p>
<div>
<div id="highlighter_600326" class="syntaxhighlighter  cpp">
<table border="0" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td class="gutter">
<div class="line number1 index0 alt2">1</div>
<div class="line number2 index1 alt1">2</div>
<div class="line number3 index2 alt2">3</div>
<div class="line number4 index3 alt1">4</div>
<div class="line number5 index4 alt2">5</div>
<div class="line number6 index5 alt1">6</div>
<div class="line number7 index6 alt2">7</div>
<div class="line number8 index7 alt1">8</div>
<div class="line number9 index8 alt2">9</div>
<div class="line number10 index9 alt1">10</div></td>
<td class="code">
<div class="container">
<div class="line number1 index0 alt2"><code class="cpp keyword bold">class</code> <code class="cpp plain">SomeType {</code></div>
<div class="line number2 index1 alt1"><code class="cpp keyword bold">private</code><code class="cpp plain">:</code></div>
<div class="line number3 index2 alt2"><code class="cpp spaces">&nbsp;&nbsp;</code><code class="cpp color1 bold">int</code> <code class="cpp plain">number;</code></div>
<div class="line number4 index3 alt1"><code class="cpp spaces">&nbsp;&nbsp;</code><code class="cpp plain">string name;</code></div>
<div class="line number5 index4 alt2"><code class="cpp spaces">&nbsp;&nbsp;</code><code class="cpp plain">SomeType( </code><code class="cpp color1 bold">int</code> <code class="cpp plain">i, string&amp;amp; s ) : number(i), name(s){}</code></div>
<div class="line number6 index5 alt1"><code class="cpp keyword bold">public</code><code class="cpp plain">:</code></div>
<div class="line number7 index6 alt2"><code class="cpp spaces">&nbsp;&nbsp;</code><code class="cpp plain">SomeType( )&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : SomeType( 0, </code><code class="cpp string">"invalid"</code> <code class="cpp plain">){}</code></div>
<div class="line number8 index7 alt1"><code class="cpp spaces">&nbsp;&nbsp;</code><code class="cpp plain">SomeType( </code><code class="cpp color1 bold">int</code> <code class="cpp plain">i )&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : SomeType( i, </code><code class="cpp string">"guest"</code> <code class="cpp plain">){}</code></div>
<div class="line number9 index8 alt2"><code class="cpp spaces">&nbsp;&nbsp;</code><code class="cpp plain">SomeType( string&amp;amp; s ) : SomeType( 1, s ){ PostInit(); }</code></div>
<div class="line number10 index9 alt1"><code class="cpp plain">};</code></div></div></td></tr></tbody></table></div></div>
<p>但是，为了方便并不足让&#8220;委托构造&#8221;这个事出现，最主要的问题是，基类的构造不能直接成为派生类的构造，就算是基类的构造函数够了，派生类还要自己写自己的构造函数：</p>
<div>
<div id="highlighter_561509" class="syntaxhighlighter  cpp">
<table border="0" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td class="gutter">
<div class="line number1 index0 alt2">1</div>
<div class="line number2 index1 alt1">2</div>
<div class="line number3 index2 alt2">3</div>
<div class="line number4 index3 alt1">4</div>
<div class="line number5 index4 alt2">5</div>
<div class="line number6 index5 alt1">6</div>
<div class="line number7 index6 alt2">7</div>
<div class="line number8 index7 alt1">8</div>
<div class="line number9 index8 alt2">9</div>
<div class="line number10 index9 alt1">10</div>
<div class="line number11 index10 alt2">11</div></td>
<td class="code">
<div class="container">
<div class="line number1 index0 alt2"><code class="cpp keyword bold">class</code> <code class="cpp plain">BaseClass</code></div>
<div class="line number2 index1 alt1"><code class="cpp plain">{</code></div>
<div class="line number3 index2 alt2"><code class="cpp keyword bold">public</code><code class="cpp plain">:</code></div>
<div class="line number4 index3 alt1"><code class="cpp spaces">&nbsp;&nbsp;</code><code class="cpp plain">BaseClass(</code><code class="cpp color1 bold">int</code> <code class="cpp plain">iValue);</code></div>
<div class="line number5 index4 alt2"><code class="cpp plain">};</code></div>
<div class="line number6 index5 alt1">&nbsp;</div>
<div class="line number7 index6 alt2"><code class="cpp keyword bold">class</code> <code class="cpp plain">DerivedClass : </code><code class="cpp keyword bold">public</code> <code class="cpp plain">BaseClass</code></div>
<div class="line number8 index7 alt1"><code class="cpp plain">{</code></div>
<div class="line number9 index8 alt2"><code class="cpp keyword bold">public</code><code class="cpp plain">:</code></div>
<div class="line number10 index9 alt1"><code class="cpp spaces">&nbsp;&nbsp;</code><code class="cpp keyword bold">using</code> <code class="cpp plain">BaseClass::BaseClass;</code></div>
<div class="line number11 index10 alt2"><code class="cpp plain">};</code></div></div></td></tr></tbody></table></div></div>
<p>上例中，派生类手动继承基类的构造函数， 编译器可以使用基类的构造函数完成派生类的构造。 而将基类的构造函数带入派生类的动作 无法选择性地部分带入， 所以，要不就是继承基类全部的构造函数，要不就是一个都不继承(不手动带入)。 此外，若牵涉到多重继承，从多个基类继承而来的构造函数不可以有相同的函数签名(signature)。 而派生类的新加入的构造函数也不可以和继承而来的基类构造函数有相同的函数签名，因为这相当于重复声明。（所谓函数签名就是函数的参数类型和顺序不）</p>
<h4 class="color-programming"><a name="t8"></a>右值引用和move语义</h4>
<p>在老版的C++中，临时性变量（称为右值&#8221;R-values&#8221;，位于赋值操作符之右）经常用作交换两个变量。比如下面的示例中的tmp变量。示例中的那个函数需要传递两个string的引用，但是在交换的过程中产生了对象的构造，内存的分配还有对象的拷贝构造等等动作，成本比较高。</p>
<div>
<div id="highlighter_115614" class="syntaxhighlighter  cpp">
<table border="0" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td class="gutter">
<div class="line number1 index0 alt2">1</div>
<div class="line number2 index1 alt1">2</div>
<div class="line number3 index2 alt2">3</div>
<div class="line number4 index3 alt1">4</div>
<div class="line number5 index4 alt2">5</div>
<div class="line number6 index5 alt1">6</div></td>
<td class="code">
<div class="container">
<div class="line number1 index0 alt2"><code class="cpp keyword bold">void</code> <code class="cpp plain">naiveswap(string &amp;amp;a, string &amp;amp;b)</code></div>
<div class="line number2 index1 alt1"><code class="cpp plain">{</code></div>
<div class="line number3 index2 alt2"><code class="cpp spaces">&nbsp;</code><code class="cpp plain">string temp = a;</code></div>
<div class="line number4 index3 alt1"><code class="cpp spaces">&nbsp;</code><code class="cpp plain">a=b;</code></div>
<div class="line number5 index4 alt2"><code class="cpp spaces">&nbsp;</code><code class="cpp plain">b=temp;</code></div>
<div class="line number6 index5 alt1"><code class="cpp plain">}</code></div></div></td></tr></tbody></table></div></div>
<p>C++ 11增加一个新的引用（reference）类型称作右值引用（R-value reference），标记为<tt>typename &amp;&amp;</tt>。他们能够以non-const值的方式传入，允许对象去改动他们。这项修正允许特定对象创造出move语义。</p>
<p>举例而言，上面那个例子中，string类中保存了一个动态内存分存的char*指针，如果一个string对象发生拷贝构造（如：函数返回），string类里的char*内存只能通过创建一个新的临时对象，并把函数内的对象的内存copy到这个新的对象中，然后销毁临时对象及其内存。<strong>这是原来C++性能上重点被批评的事</strong>。</p>
<p>能过右值引用，string的构造函数需要改成&#8220;move构造函数&#8221;，如下所示。这样一来，使得对某个<span style="font-family: monospace">stirng</span>的右值引用可以单纯地从右值复制其内部C-style的指针到新的string，然后留下空的右值。这个操作不需要内存数组的复制，而且空的暂时对象的析构也不会释放内存。其更有效率。</p>
<div>
<div id="highlighter_780965" class="syntaxhighlighter  cpp">
<table border="0" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td class="gutter">
<div class="line number1 index0 alt2">1</div>
<div class="line number2 index1 alt1">2</div>
<div class="line number3 index2 alt2">3</div>
<div class="line number4 index3 alt1">4</div>
<div class="line number5 index4 alt2">5</div></td>
<td class="code">
<div class="container">
<div class="line number1 index0 alt2"><code class="cpp keyword bold">class</code> <code class="cpp plain">string</code></div>
<div class="line number2 index1 alt1"><code class="cpp plain">{</code></div>
<div class="line number3 index2 alt2"><code class="cpp spaces">&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="cpp plain">string (string&amp;&amp;); </code><code class="cpp comments">//move constructor</code></div>
<div class="line number4 index3 alt1"><code class="cpp spaces">&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="cpp plain">string&amp;&amp; operator=(string&amp;&amp;); </code><code class="cpp comments">//move assignment operator</code></div>
<div class="line number5 index4 alt2"><code class="cpp plain">};</code></div></div></td></tr></tbody></table></div></div>
<p>The C++11 STL中广泛地使用了右值引用和move语议。因此，很多算法和容器的性能都被优化了。</p>
<h4 class="color-programming"><a name="t9"></a>C++ 11 STL 标准库</h4>
<p>C++ STL库在2003年经历了很大的整容手术&nbsp;<a href="http://www.devsource.com/c/a/Languages/Grok-The-New-Features-in-Standard-C/">Library Technical Report 1</a> (TR1)。 TR1 中出现了很多新的容器类 (<code>unordered_set</code>, <code>unordered_map</code>, <code>unordered_multiset</code>, 和&nbsp;<code>unordered_multimap</code>) 以及一些新的库支持诸如：正则表达式， tuples，函数对象包装，等等。 C++11 批准了 TR1 成为正式的C++标准，还有一些TR1 后新加的一些库，从而成为了新的C++ 11 STL标准库。这个库主要包含下面的功能：</p>
<h5 class="color-programming"><a name="t10"></a>线程库</h5>
<p>这们就不多说了，以前的STL饱受线程安全的批评。现在好 了。C++ 11 支持线程类了。这将涉及两个部分：第一、设计一个可以使多个线程在一个进程中共存的内存模型；第二、为线程之间的交互提供支持。第二部分将由程序库提供支持。大家可以看看<a href="http://en.wikipedia.org/wiki/Futures_and_promises" target="_blank">promises and futures</a>，其用于对象的同步。&nbsp;<a href="http://www.stdthread.co.uk/doc/headers/future/async.html">async()</a>&nbsp;函数模板用于发起并发任务，而&nbsp;<a href="http://www.devx.com/cplus/10MinuteSolution/37436">thread_local</a>&nbsp;为线程内的数据指定存储类型。更多的东西，可以查看 Anthony Williams的&nbsp;<a href="http://www.devx.com/SpecialReports/Article/38883">Simpler Multithreading in C++0x</a>.</p>
<h5 class="color-programming"><a name="t11"></a>新型智能指针</h5>
<p>C++98 的知能指针是&nbsp;<code>auto_ptr， 在C++ 11中被废弃了。</code>C++11 &nbsp;引入了两个指针类：&nbsp;<a href="http://www.informit.com/guides/content.aspx?g=cplusplus&amp;seqNum=239">shared_ptr</a> 和 <a href="http://www.informit.com/guides/content.aspx?g=cplusplus&amp;seqNum=400">unique_ptr</a>。 shared_ptr只是单纯的引用计数指针，<code>unique_ptr 是用来取代<code>auto_ptr</code></code>。&nbsp;<code>unique_ptr</code>&nbsp;提供&nbsp;<code>auto_ptr</code>&nbsp;大部份特性，唯一的例外是&nbsp;<code>auto_ptr</code>&nbsp;的不安全、隐性的左值搬移。不像&nbsp;<code>auto_ptr</code>，<code>unique_ptr</code>&nbsp;可以存放在 C++0x 提出的那些能察觉搬移动作的容器之中。</p>
<p>为什么要这么干？大家可以看看《More Effective C++》中对 auto_ptr的讨论。</p>
<h5 class="color-programming"><a name="t12"></a>新的算法</h5>
<p>定义了一些新的算法：&nbsp;<code>all_of()</code>, <code>any_of()</code>&nbsp;和&nbsp;<code>none_of()。</code></p>
<div>
<div id="highlighter_454948" class="syntaxhighlighter  cpp">
<table border="0" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td class="gutter">
<div class="line number1 index0 alt2">1</div>
<div class="line number2 index1 alt1">2</div>
<div class="line number3 index2 alt2">3</div>
<div class="line number4 index3 alt1">4</div>
<div class="line number5 index4 alt2">5</div>
<div class="line number6 index5 alt1">6</div>
<div class="line number7 index6 alt2">7</div>
<div class="line number8 index7 alt1">8</div></td>
<td class="code">
<div class="container">
<div class="line number1 index0 alt2"><code class="cpp preprocessor">#include &amp;lt;algorithm&amp;gt;</code></div>
<div class="line number2 index1 alt1"><code class="cpp comments">//C++11 code</code></div>
<div class="line number3 index2 alt2"><code class="cpp comments">//are all of the elements positive?</code></div>
<div class="line number4 index3 alt1"><code class="cpp plain">all_of(first, first+n, ispositive()); </code><code class="cpp comments">//false</code></div>
<div class="line number5 index4 alt2"><code class="cpp comments">//is there at least one positive element?</code></div>
<div class="line number6 index5 alt1"><code class="cpp plain">any_of(first, first+n, ispositive());</code><code class="cpp comments">//true</code></div>
<div class="line number7 index6 alt2"><code class="cpp comments">// are none of the elements positive?</code></div>
<div class="line number8 index7 alt1"><code class="cpp plain">none_of(first, first+n, ispositive()); </code><code class="cpp comments">//false</code></div></div></td></tr></tbody></table></div></div>
<p>使用新的copy_n()算法，你可以很方便地拷贝数组。</p>
<div>
<div id="highlighter_647452" class="syntaxhighlighter  cpp">
<table border="0" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td class="gutter">
<div class="line number1 index0 alt2">1</div>
<div class="line number2 index1 alt1">2</div>
<div class="line number3 index2 alt2">3</div>
<div class="line number4 index3 alt1">4</div>
<div class="line number5 index4 alt2">5</div></td>
<td class="code">
<div class="container">
<div class="line number1 index0 alt2"><code class="cpp preprocessor">#include &amp;lt;algorithm&amp;gt;</code></div>
<div class="line number2 index1 alt1"><code class="cpp color1 bold">int</code> <code class="cpp plain">source[5]={0,12,34,50,80};</code></div>
<div class="line number3 index2 alt2"><code class="cpp color1 bold">int</code> <code class="cpp plain">target[5];</code></div>
<div class="line number4 index3 alt1"><code class="cpp comments">//copy 5 elements from source to target</code></div>
<div class="line number5 index4 alt2"><code class="cpp plain">copy_n(source,5,target);</code></div></div></td></tr></tbody></table></div></div>
<p>使用&nbsp;<code>iota()</code>&nbsp;可以用来创建递增的数列。如下例所示：</p>
<div>
<div id="highlighter_195189" class="syntaxhighlighter  cpp">
<table border="0" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td class="gutter">
<div class="line number1 index0 alt2">1</div>
<div class="line number2 index1 alt1">2</div>
<div class="line number3 index2 alt2">3</div>
<div class="line number4 index3 alt1">4</div>
<div class="line number5 index4 alt2">5</div></td>
<td class="code">
<div class="container">
<div class="line number1 index0 alt2"><code class="cpp plain">include &amp;lt;numeric&amp;gt;</code></div>
<div class="line number2 index1 alt1"><code class="cpp color1 bold">int</code> <code class="cpp plain">a[5]={0};</code></div>
<div class="line number3 index2 alt2"><code class="cpp color1 bold">char</code> <code class="cpp plain">c[3]={0};</code></div>
<div class="line number4 index3 alt1"><code class="cpp plain">iota(a, a+5, 10); </code><code class="cpp comments">//changes a to {10,11,12,13,14}</code></div>
<div class="line number5 index4 alt2"><code class="cpp plain">iota(c, c+3, </code><code class="cpp string">'a'</code><code class="cpp plain">); </code><code class="cpp comments">//{'a','b','c'}</code></div></div></td></tr></tbody></table></div></div>
<p>总之，看下来，C++11 还是很学院派，很多实用的东西还是没有，比如： XML，sockets，reflection，当然还有垃圾回收。看来要等到C++ 20了。呵呵。不过C++ 11在性能上还是很快。参看 Google&#8217;s <a href="http://www.itproportal.com/2011/06/07/googles-rates-c-most-complex-highest-performing-language/">benchmark tests</a>。原文还引用Stroustrup 的观点：C++11 是一门新的语言&#8212;&#8212;一个更好的 C++。</p>
<p>如果把所有的改变都列出来，你会发现真多啊。我估计C++ Primer那本书的厚度要增加至少30%以上。C++的门槛会不会越来越高了呢？我不知道，但我个人觉得这门语言的确是变得越来越令人望而却步了。（想起了某人和我说的一句话&#8212;&#8212;学技术真的是太累了，还是搞方法论好混些？）</p><img src ="http://www.cppblog.com/tianbianlan/aggbug/199992.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/tianbianlan/" target="_blank">天边蓝</a> 2013-05-05 21:26 <a href="http://www.cppblog.com/tianbianlan/archive/2013/05/05/199992.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>各编译器对于C++11新特性的支持情况</title><link>http://www.cppblog.com/tianbianlan/archive/2013/05/05/199991.html</link><dc:creator>天边蓝</dc:creator><author>天边蓝</author><pubDate>Sun, 05 May 2013 13:11:00 GMT</pubDate><guid>http://www.cppblog.com/tianbianlan/archive/2013/05/05/199991.html</guid><wfw:comment>http://www.cppblog.com/tianbianlan/comments/199991.html</wfw:comment><comments>http://www.cppblog.com/tianbianlan/archive/2013/05/05/199991.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/tianbianlan/comments/commentRss/199991.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/tianbianlan/services/trackbacks/199991.html</trackback:ping><description><![CDATA[<p class="line874">http://wiki.apache.org/stdcxx/C%2B%2B0xCompilerSupport<br />The following table lists C++0x features and their support in popular compilers. <span id="line-2" class="anchor"></span>
<div>
<table style="text-align: center; width: 1201px; height: 2349px">
<tbody>
<tr>
<td style="text-align: center" colspan="12">
<p class="line862">Status Of C++ 0x Language Features in Compilers </p></td></tr>
<tr style="background-color: #b0e0e6; font-weight: bold">
<td><span id="line-3" class="anchor"></span>
<p class="line862">C++ 0x FEATURE </p></td>
<td style="width: 12%">
<p class="line862">PAPER(S) </p></td>
<td>
<p class="line862">HP aCC </p></td>
<td>
<p class="line862">EDG eccp </p></td>
<td>
<p class="line891"><a class="http" href="http://gcc.gnu.org/projects/cxx0x.html">GCC</a> </p></td>
<td>
<p class="line891"><a class="http" href="http://software.intel.com/en-us/articles/c0x-features-supported-by-intel-c-compiler/">Intel C++</a> </p></td>
<td>
<p class="line891"><a class="http" href="http://blogs.msdn.com/b/vcblog/archive/2011/09/12/10209291.aspx">MSVC</a> </p></td>
<td>
<p class="line891"><a class="https" href="https://www.ibm.com/developerworks/mydeveloperworks/blogs/5894415f-be62-4bc0-81c5-3956e82276f3/entry/xlc_compiler_s_c_11_support50?lang=en">IBM XLC++</a> </p></td>
<td>
<p class="line862">Sun/ Oracle C++ </p></td>
<td>
<p class="line891"><a class="http" href="http://docwiki.embarcadero.com/RADStudio/XE3/en/C++11_Features_(BCC64)">Embarcadero C++ Builder</a> </p></td>
<td>
<p class="line862">Digital Mars C++ </p></td>
<td>
<p class="line891"><a class="http" href="http://clang.llvm.org/cxx_status.html">Clang</a> </p></td></tr>
<tr>
<td style="text-align: left"><span id="line-4" class="anchor"></span>
<p class="line891"><tt class="backtick">alignas</tt> </p></td>
<td>
<p class="line891"><a class="http" href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2341.pdf">N2341</a> </p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862">4.8 </p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862">3.0 </p></td></tr>
<tr>
<td style="text-align: left"><span id="line-5" class="anchor"></span>
<p class="line891"><tt class="backtick">alignof</tt> </p></td>
<td>
<p class="line891"><a class="http" href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2341.pdf">N2341</a> </p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862">4.5 </p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862">Yes </p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862">2.9 </p></td></tr>
<tr>
<td style="text-align: left"><span id="line-6" class="anchor"></span>
<p class="line862">Atomic operations </p></td>
<td>
<p class="line891"><a class="http" href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2427.html">N2427</a> </p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862">4.4 </p></td>
<td>
<p class="line862">13.0 </p></td>
<td>
<p class="line862">11.0 </p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862">3.1 </p></td></tr>
<tr>
<td style="text-align: left"><span id="line-7" class="anchor"></span>
<p class="line891"><tt class="backtick">auto</tt> </p></td>
<td>
<p class="line862">v0.9: <a class="http" href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n1984.pdf">N1984</a>, v1.0: <a class="http" href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2546.htm">N2546</a> </p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862">4.1(v0.9) </p></td>
<td>
<p class="line862">4.4(v1.0) </p></td>
<td>
<p class="line862">11.0(v0.9) </p></td>
<td>
<p class="line862">10.0(v0.9) </p></td>
<td>
<p class="line862">11.1 (V1.0) </p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862">Yes </p></td></tr>
<tr>
<td style="text-align: left"><span id="line-8" class="anchor"></span>
<p class="line862">C99 preprocessor </p></td>
<td>
<p class="line891"><a class="http" href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2004/n1653.htm">N1653</a> </p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862">4.3 </p></td>
<td>
<p class="line862">11.1 </p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862">10.1 </p></td>
<td>
<p class="line862">5.9 </p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862">Yes </p></td>
<td>
<p class="line862">Yes </p></td></tr>
<tr style="background-color: #d3d3d3">
<td style="text-align: left"><span id="line-9" class="anchor"></span>
<p class="line891"><em>Concepts <sup>[removed]</sup></em> </p></td>
<td>
<p class="line891"><a class="http" href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2617.pdf">N2617</a> </p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line891"><a class="nonexistent" href="http://wiki.apache.org/stdcxx/ConceptGcc">ConceptGcc</a> </p></td>
<td>
<p class="line891"><br /></p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862"></p></td></tr>
<tr>
<td style="text-align: left"><span id="line-10" class="anchor"></span>
<p class="line891"><tt class="backtick">constexpr</tt> </p></td>
<td>
<p class="line891"><a class="http" href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2235.pdf">N2235</a> </p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862">4.6 </p></td>
<td>
<p class="line862">13.0 </p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862">12.1 </p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862">3.1 </p></td></tr>
<tr>
<td style="text-align: left"><span id="line-11" class="anchor"></span>
<p class="line891"><tt class="backtick">decltype</tt> </p></td>
<td>
<p class="line862">v1.0: <a class="http" href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2343.pdf">N2343</a>, v1.1: <a class="http" href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3276.pdf">N3276</a> </p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862">4.1(v1.0) </p></td>
<td>
<p class="line862">4.3(v1.0) 4.8.1(v1.1) </p></td>
<td>
<p class="line862">11.0(v1.0) </p></td>
<td>
<p class="line862">10.0(v1.0), 11.0(v1.1) </p></td>
<td>
<p class="line862">11.1 (V1.0) </p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862">Yes </p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862">2.9 </p></td></tr>
<tr>
<td style="text-align: left"><span id="line-12" class="anchor"></span>
<p class="line862">Defaulted And Deleted Functions </p></td>
<td>
<p class="line891"><a class="http" href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2346.htm">N2346</a> </p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862">4.1 </p></td>
<td>
<p class="line862">4.4 </p></td>
<td>
<p class="line862">12.0 </p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862">3.0 </p></td></tr>
<tr>
<td style="text-align: left"><span id="line-13" class="anchor"></span>
<p class="line862">Delegating Constructors </p></td>
<td>
<p class="line891"><a class="http" href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n1986.pdf">N1986</a> </p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862">4.7 </p></td>
<td>
<p class="line891"><br /></p></td>
<td>
<p class="line862">11.0 nov'12 </p></td>
<td>
<p class="line862">11.1 </p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862">3.0 </p></td></tr>
<tr>
<td style="text-align: left"><span id="line-14" class="anchor"></span>
<p class="line862">Explicit conversion operators </p></td>
<td>
<p class="line891"><a class="http" href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2437.pdf">N2437</a> </p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862">4.5 </p></td>
<td>
<p class="line862">13.0 </p></td>
<td>
<p class="line862">11.0 nov'12 </p></td>
<td>
<p class="line862">12.1 </p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862">Yes </p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862">3.0 </p></td></tr>
<tr>
<td style="text-align: left"><span id="line-15" class="anchor"></span>
<p class="line862">Extended <tt class="backtick">friend</tt> Declarations </p></td>
<td>
<p class="line891"><a class="http" href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1791.pdf">N1791</a> </p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862">4.1 </p></td>
<td>
<p class="line862">4.7 </p></td>
<td>
<p class="line862">11.0 </p></td>
<td>
<p class="line862">10.0*** </p></td>
<td>
<p class="line891"><a class="nonexistent" href="http://wiki.apache.org/stdcxx/V1R11">V1R11</a>,11.1 </p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862">2.9 </p></td></tr>
<tr>
<td style="text-align: left"><span id="line-16" class="anchor"></span>
<p class="line891"><tt class="backtick">extern&nbsp;template</tt> </p></td>
<td>
<p class="line891"><a class="http" href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n1987.htm">N1987</a> </p></td>
<td>
<p class="line862">3, 5, 6 </p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862">3.3 </p></td>
<td>
<p class="line862">9 </p></td>
<td>
<p class="line862">6.0 </p></td>
<td>
<p class="line891"><a class="nonexistent" href="http://wiki.apache.org/stdcxx/V1R11">V1R11</a>,11.1 </p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862">Yes </p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862">Yes </p></td></tr>
<tr>
<td style="text-align: left"><span id="line-17" class="anchor"></span>
<p class="line862">Forward declarations for enums </p></td>
<td>
<p class="line891"><a class="http" href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2764.pdf">N2764</a> </p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862">4.6 </p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862">11.0 </p></td>
<td>
<p class="line862">12.1 </p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862">3.1 </p></td></tr>
<tr>
<td style="text-align: left"><span id="line-18" class="anchor"></span>
<p class="line862">Inheriting Constructors </p></td>
<td>
<p class="line891"><a class="http" href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2540.htm">N2540</a> </p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862">4.8 </p></td>
<td>
<p class="line891"><br /></p></td>
<td>
<p class="line891"><br /></p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862"></p></td></tr>
<tr>
<td style="text-align: left"><span id="line-19" class="anchor"></span>
<p class="line862">Initializer Lists </p></td>
<td>
<p class="line891"><a class="http" href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2672.htm">N2672</a> </p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862">4.4 </p></td>
<td>
<p class="line862">13.0 </p></td>
<td>
<p class="line862">11.0 nov'12 </p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862">3.1 </p></td></tr>
<tr>
<td style="text-align: left"><span id="line-20" class="anchor"></span>
<p class="line862">Lambda expressions and closures </p></td>
<td>
<p class="line862">v0.9: <a class="http" href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2550.pdf">N2550</a>, v1.0: <a class="http" href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2658.pdf">N2658</a>, v1.1: <a class="http" href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2009/n2927.pdf">N2927</a> </p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862">4.1(v0.9) </p></td>
<td>
<p class="line862">4.5(v1.1) </p></td>
<td>
<p class="line862">11.0(v0.9)<br />12.0(v1.0) </p></td>
<td>
<p class="line862">10.0(v1.0), 11.0(v1.1) </p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862">3.1 </p></td></tr>
<tr>
<td style="text-align: left"><span id="line-21" class="anchor"></span>
<p class="line862">Local and Unnamed Types as Template Arguments </p></td>
<td>
<p class="line891"><a class="http" href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2657.htm">N2657</a> </p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862">4.5 </p></td>
<td>
<p class="line862">12.0 </p></td>
<td>
<p class="line862">10.0 </p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862">2.9 </p></td></tr>
<tr>
<td style="text-align: left"><span id="line-22" class="anchor"></span>
<p class="line891"><tt class="backtick">long&nbsp;long</tt> </p></td>
<td>
<p class="line891"><a class="http" href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1811.pdf">N1811</a> </p></td>
<td>
<p class="line862">Yes </p></td>
<td>
<p class="line862">Yes </p></td>
<td>
<p class="line862">Yes </p></td>
<td>
<p class="line862">Yes </p></td>
<td>
<p class="line862">Yes </p></td>
<td>
<p class="line862">Yes </p></td>
<td>
<p class="line862">Yes </p></td>
<td>
<p class="line862">Yes </p></td>
<td>
<p class="line862">Yes </p></td>
<td>
<p class="line862">Yes </p></td></tr>
<tr>
<td style="text-align: left"><span id="line-23" class="anchor"></span>
<p class="line862">Namespace Association </p></td>
<td>
<p class="line891"><a class="http" href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2535.htm">N2535</a> </p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862">4.4 </p></td>
<td>
<p class="line891"><br /></p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862">11.1 </p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862">2.9 </p></td></tr>
<tr>
<td style="text-align: left"><span id="line-24" class="anchor"></span>
<p class="line862">New character types </p></td>
<td>
<p class="line891"><a class="http" href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2249.html">N2249</a> </p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862">4.4 </p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862">2.9 </p></td></tr>
<tr>
<td style="text-align: left"><span id="line-25" class="anchor"></span>
<p class="line862">New function declaration syntax for deduced return types </p></td>
<td>
<p class="line891"><a class="http" href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2541.htm">N2541</a> </p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862">4.1 </p></td>
<td>
<p class="line862">4.4 </p></td>
<td>
<p class="line862">12.1 </p></td>
<td>
<p class="line862">10.0 </p></td>
<td>
<p class="line862">12.1 </p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862">2.9 </p></td></tr>
<tr>
<td style="text-align: left"><span id="line-26" class="anchor"></span>
<p class="line891"><tt class="backtick">nullptr</tt> </p></td>
<td>
<p class="line891"><a class="http" href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2431.pdf">N2431</a> </p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862">4.6 </p></td>
<td>
<p class="line862">12.1* </p></td>
<td>
<p class="line862">10.0 </p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862">2.9 </p></td></tr>
<tr>
<td style="text-align: left"><span id="line-27" class="anchor"></span>
<p class="line862">Unicode String Literals </p></td>
<td>
<p class="line891"><a class="http" href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2442.htm">N2442</a> </p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862">4.4 </p></td>
<td>
<p class="line862">11.0* </p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862">5.7 </p></td>
<td>
<p class="line862">Yes </p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862">3.0 </p></td></tr>
<tr>
<td style="text-align: left"><span id="line-28" class="anchor"></span>
<p class="line862">Raw String Literals </p></td>
<td>
<p class="line891"><a class="http" href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2442.htm">N2442</a> </p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862">4.5 </p></td>
<td>
<p class="line891"><br /></p></td>
<td>
<p class="line862">11.0 nov'12 </p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862">Yes </p></td></tr>
<tr>
<td style="text-align: left"><span id="line-29" class="anchor"></span>
<p class="line862">User-defined Literals </p></td>
<td>
<p class="line891"><a class="http" href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2765.html">N2765</a> </p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862">4.7 </p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862">3.1 </p></td></tr>
<tr>
<td style="text-align: left"><span id="line-30" class="anchor"></span>
<p class="line862">Right Angle Brackets </p></td>
<td>
<p class="line891"><a class="http" href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1757.html">N1757</a> </p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862">4.1 </p></td>
<td>
<p class="line862">4.3 </p></td>
<td>
<p class="line862">11.0 </p></td>
<td>
<p class="line862">8.0 </p></td>
<td>
<p class="line862">12.1 </p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862">Yes </p></td></tr>
<tr>
<td style="text-align: left"><span id="line-31" class="anchor"></span>
<p class="line862">R-Value References, std::move </p></td>
<td>
<p class="line862">v1.0: <a class="http" href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n2118.html">N2118</a>, v2.0: <a class="http" href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2009/n2844.html">N2844</a>, v2.1: <a class="http" href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1138">N2844+</a>, v3.0: <a class="http" href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2010/n3053.html">N3053</a> </p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862">4.1(v1.0) </p></td>
<td>
<p class="line862">4.3(v1.0)<br />4.5(v2.1)<br />4.6(v3.0) </p></td>
<td>
<p class="line862">11.1(v1.0)<br />12.0(v2.0) </p></td>
<td>
<p class="line862">10.0(v2.0), 11.0(v2.1) </p></td>
<td>
<p class="line862">12.1(v2.1) </p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862">Yes </p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862">Yes </p></td></tr>
<tr>
<td style="text-align: left"><span id="line-32" class="anchor"></span>
<p class="line891"><tt class="backtick">static_assert</tt> </p></td>
<td>
<p class="line891"><a class="http" href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2004/n1720.html">N1720</a> </p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862">4.1 </p></td>
<td>
<p class="line862">4.3 </p></td>
<td>
<p class="line862">11.0 </p></td>
<td>
<p class="line862">10.0 </p></td>
<td>
<p class="line862">11.1 </p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862">Yes </p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862">2.9 </p></td></tr>
<tr>
<td style="text-align: left"><span id="line-33" class="anchor"></span>
<p class="line862">Strongly-typed <tt class="backtick">enum</tt>s </p></td>
<td>
<p class="line891"><a class="http" href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2347.pdf">N2347</a> </p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862">4.4 </p></td>
<td>
<p class="line862">12.0 </p></td>
<td>
<p class="line862">11.0 </p></td>
<td>
<p class="line862">12.1 </p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862">Yes </p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862">2.9 </p></td></tr>
<tr>
<td style="text-align: left"><span id="line-34" class="anchor"></span>
<p class="line862">Template aliases </p></td>
<td>
<p class="line891"><a class="http" href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2258.pdf">N2258</a> </p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862">4.7 </p></td>
<td>
<p class="line862">12.1 </p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862">3.0 </p></td></tr>
<tr>
<td style="text-align: left"><span id="line-35" class="anchor"></span>
<p class="line862">Thread-Local Storage </p></td>
<td>
<p class="line891"><a class="http" href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2659.htm">N2659</a> </p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862">4.8 (4.4****) </p></td>
<td>
<p class="line862">11.1***<br /></p></td>
<td>
<p class="line862">10.0*** </p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862">5.9*** </p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862">2.9**** </p></td></tr>
<tr>
<td style="text-align: left"><span id="line-36" class="anchor"></span>
<p class="line862">Unrestricted Unions </p></td>
<td>
<p class="line891"><a class="http" href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2544.pdf">N2544</a> </p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862">4.6 </p></td>
<td>
<p class="line891"><br /></p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862">3.0 </p></td></tr>
<tr>
<td style="text-align: left"><span id="line-37" class="anchor"></span>
<p class="line862">Built-in Type Traits </p></td>
<td>
<p class="line891"><a class="http" href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1836.pdf">N1836</a> </p></td>
<td>
<p class="line862">6.16 </p></td>
<td>
<p class="line862">4.0 </p></td>
<td>
<p class="line862">4.3 </p></td>
<td>
<p class="line862">10.0 </p></td>
<td>
<p class="line862">8.0 </p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862">Yes </p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862">3.0 </p></td></tr>
<tr>
<td style="text-align: left"><span id="line-38" class="anchor"></span>
<p class="line862">Variadic Templates </p></td>
<td>
<p class="line862">v0.9: <a class="http" href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2242.pdf">N2242</a>, v1.0: <a class="http" href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2555.pdf">N2555</a> </p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862">4.1(v0.9) </p></td>
<td>
<p class="line862">4.3(v0.9) 4.4(v1.0) </p></td>
<td>
<p class="line862">12.1(v0.9) </p></td>
<td>
<p class="line862">11.0 nov'12 </p></td>
<td>
<p class="line862">11.1 (v0.9) </p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862">2.9(1.0) </p></td></tr>
<tr>
<td style="text-align: left"><span id="line-39" class="anchor"></span>
<p class="line862">Range-based for-loop </p></td>
<td>
<p class="line891"><a class="http" href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2009/n2930.html">N2930</a> </p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862">4.6 </p></td>
<td>
<p class="line862">13.0 </p></td>
<td>
<p class="line862">11.0 </p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862">3.0 </p></td></tr>
<tr>
<td style="text-align: left"><span id="line-40" class="anchor"></span>
<p class="line862">override and final </p></td>
<td>
<p class="line862">v0.8: <a class="http" href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2009/n2928.htm">N2928</a>, v0.9: <a class="http" href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2010/n3206.htm">N3206</a>, v1.0: <a class="http" href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3272.htm">N3272</a> </p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862">4.7 </p></td>
<td>
<p class="line862">12.0(v0.8)*** </p></td>
<td>
<p class="line862">8.0(v0.8)*** 11.0(v1.0) </p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862">2.9 </p></td></tr>
<tr>
<td style="text-align: left"><span id="line-41" class="anchor"></span>
<p class="line862">Attributes </p></td>
<td>
<p class="line891"><a class="http" href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2761.pdf">N2761</a> </p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862">4.8 </p></td>
<td>
<p class="line862">12.1 </p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862"></p></td></tr>
<tr>
<td style="text-align: left"><span id="line-42" class="anchor"></span>
<p class="line862">ref-qualifiers </p></td>
<td>
<p class="line891"><a class="http" href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2439.htm">N2439</a> </p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862">4.8.1 </p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862">2.9 </p></td></tr>
<tr>
<td style="text-align: left"><span id="line-43" class="anchor"></span>
<p class="line862">Non-static data member initializers </p></td>
<td>
<p class="line891"><a class="http" href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2756.htm">N2756</a> </p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862">4.7 </p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862">3.0 </p></td></tr>
<tr>
<td style="text-align: left"><span id="line-44" class="anchor"></span>
<p class="line862">Dynamic initialization and destruction with concurrency (Magic statics) </p></td>
<td>
<p class="line891"><a class="http" href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2660.htm">N2660</a> </p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862">4.3 </p></td>
<td>
<p class="line862">? </p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862"></p></td>
<td>
<p class="line862">2.9 </p></td></tr></tbody></table></div><span id="line-45" class="anchor"></span><span id="line-46" class="anchor"></span><span id="line-47" class="anchor"></span><span id="line-48" class="anchor"></span><span id="line-49" class="anchor"></span>
<p class="line862">* &#8212; 1) unicode string literals is a feature of the EDG frontend, but it is undocumented at Intel C++ compiler (/Qoption,cpp,"--uliterals" option enables it) <br /></p> <img src ="http://www.cppblog.com/tianbianlan/aggbug/199991.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/tianbianlan/" target="_blank">天边蓝</a> 2013-05-05 21:11 <a href="http://www.cppblog.com/tianbianlan/archive/2013/05/05/199991.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>gprof——GNU性能分析工具 </title><link>http://www.cppblog.com/tianbianlan/archive/2013/04/22/199639.html</link><dc:creator>天边蓝</dc:creator><author>天边蓝</author><pubDate>Mon, 22 Apr 2013 08:39:00 GMT</pubDate><guid>http://www.cppblog.com/tianbianlan/archive/2013/04/22/199639.html</guid><wfw:comment>http://www.cppblog.com/tianbianlan/comments/199639.html</wfw:comment><comments>http://www.cppblog.com/tianbianlan/archive/2013/04/22/199639.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/tianbianlan/comments/commentRss/199639.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/tianbianlan/services/trackbacks/199639.html</trackback:ping><description><![CDATA[<address><em>转载至</em><a href="http://www.cnblogs.com/feisky/archive/2010/03/09/1681997.html"><em>http://www.cnblogs.com/feisky/archive/2010/03/09/1681997.html</em></a></address>
<h1>gprof介绍</h1>
<p>gprof是GNU profiler工具。可以显示程序运行的&#8220;flat profile&#8221;，包括每个函数的调用次数，每个函数消耗的处理器时间。也可以显示&#8220;调用图&#8221;，包括函数的调用关系，每个函数调用花费了多少时间。还可以显示&#8220;注释的源代码&#8221;，是程序源代码的一个复本，标记有程序中每行代码的执行次数。</p>
<h1>为gprof编译程序</h1>
<p><br />在编译或链接源程序的时候在编译器的<strong>命令行参数中加入&#8220;-pg&#8221;选项</strong>，编译时编译器会自动在目标代码中插入用于性能测试的代码片断，这些代码在程序在运行时采集并记录函数的调用关系和调用次数，以及采集并记录函数自身执行时间和子函数的调用时间，<strong>程序运行结束后，会在程序退出的路径下生成一个gmon.out文件</strong>。这个文件就是记录并保存下来的监控数据。可以通过命令行方式的gprof或图形化的Kprof来解读这些数据并对程序的性能进行分析。另外，如果想查看库函数的profiling，需要在编译是再加入&#8220;-lc_p&#8221;编译参数代替&#8220;-lc&#8221;编译参数，这样程序会链接libc_p.a库，才可以产生库函数的profiling信息。如果想执行一行一行的profiling，还需要加入&#8220;-g&#8221;编译参数。<br />例如如下命令行：gcc -Wall -g -pg -lc_p example.c -o example</p>
<h1><em>Gprof基本用法：</em></h1>
<p>1． 使用 -pg 编译和链接你的应用程序。</p>
<p>2． 执行你的应用程序使之生成供gprof 分析的数据。 
<p>3． 使用gprof 程序分析你的应用程序生成的数据。 
<p>$<strong>gprof -b a.out gmon.out</strong>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />Flat profile: 
<p>Each sample counts as 0.01 seconds.<br />no time accumulated 
<p>&nbsp; %&nbsp;&nbsp; cumulative&nbsp;&nbsp; self&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self&nbsp;&nbsp;&nbsp;&nbsp; total&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />time&nbsp;&nbsp; seconds&nbsp;&nbsp; seconds&nbsp;&nbsp;&nbsp; calls&nbsp; Ts/call&nbsp; Ts/call&nbsp; name&nbsp;&nbsp;&nbsp; <br />&nbsp; 0.00&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0.00&nbsp;&nbsp;&nbsp;&nbsp; 0.00&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1&nbsp;&nbsp;&nbsp;&nbsp; 0.00&nbsp;&nbsp;&nbsp;&nbsp; 0.00&nbsp; function 
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Call graph 
<p>granularity: each sample hit covers 2 byte(s) no time propagated 
<p>index % time&nbsp;&nbsp;&nbsp; self&nbsp; children&nbsp;&nbsp;&nbsp; called&nbsp;&nbsp;&nbsp;&nbsp; name<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0.00&nbsp;&nbsp;&nbsp; 0.00&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1/1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; main [8]<br />[1]&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0.0&nbsp;&nbsp;&nbsp; 0.00&nbsp;&nbsp;&nbsp; 0.00&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; function [1]<br />----------------------------------------------- 
<p>Index by function name 
<p>&nbsp;&nbsp; [1] function 
<h1>gprof产生的信息</h1>
<p><br />%&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; the percentage of the total running time of the<br />time&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; program used by this function.<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 函数使用时间占所有时间的百分比。<br />cumulative&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; a running sum of the number of seconds accounted<br />seconds&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for by this function and those listed above it.<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 函数和上列函数累计执行的时间。<br />self&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; the number of seconds accounted for by this<br />seconds&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; function alone.&nbsp; This is the major sort for this<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; listing.<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 函数本身所执行的时间。<br />calls&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; the number of times this function was invoked, if<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this function is profiled, else blank.<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 函数被调用的次数<br />self&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; the average number of milliseconds spent in this<br />ms/call&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; function per call, if this function is profiled,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else blank.<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 每一次调用花费在函数的时间microseconds。<br />total&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; the average number of milliseconds spent in this<br />ms/call&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; function and its descendents per call, if this<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; function is profiled, else blank.<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 每一次调用，花费在函数及其衍生函数的平均时间microseconds。<br />name&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; the name of the function.&nbsp; This is the minor sort<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for this listing. The index shows the location of<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; the function in the gprof listing. If the index is<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; in parenthesis it shows where it would appear in<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; the gprof listing if it were to be printed.<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 函数名</p>
<h1>命令格式</h1>
<p>gprof [可执行文件] [gmon.out文件] [其它参数] 
<p>方括号中的内容可以省略。如果省略了&#8220;可执行文件&#8221;，gprof会在当前目录下搜索a.out文件作为可执行文件，而如果省略了gmon.out文件，gprof也会在当前目录下寻找gmon.out。其它参数可以控制gprof输出内容的格式等信息。最常用的参数如下： 
<p>l -b 不再输出统计图表中每个字段的详细描述。 
<p>l -p 只输出函数的调用图（Call graph的那部分信息）。 
<p>l -q 只输出函数的时间消耗列表。 
<p>l -e Name 不再输出函数Name 及其子函数的调用图（除非它们有未被限制的其它父函数）。可以给定多个 -e 标志。一个 -e 标志只能指定一个函数。 
<p>l -E Name 不再输出函数Name 及其子函数的调用图，此标志类似于 -e 标志，但它在总时间和百分比时间的计算中排除了由函数Name 及其子函数所用的时间。 
<p>l -f Name 输出函数Name 及其子函数的调用图。可以指定多个 -f 标志。一个 -f 标志只能指定一个函数。 
<p>l -F Name 输出函数Name 及其子函数的调用图，它类似于 -f 标志，但它在总时间和百分比时间计算中仅使用所打印的例程的时间。可以指定多个 -F 标志。一个 -F 标志只能指定一个函数。-F 标志覆盖 -E 标志。 
<p>l -z 显示使用次数为零的例程（按照调用计数和累积时间计算）。 
<p>不过,gprof不能显示对象之间的继承关系,这也是它的弱点.</p><img src ="http://www.cppblog.com/tianbianlan/aggbug/199639.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/tianbianlan/" target="_blank">天边蓝</a> 2013-04-22 16:39 <a href="http://www.cppblog.com/tianbianlan/archive/2013/04/22/199639.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>【转】浅析系统的大小端模式 </title><link>http://www.cppblog.com/tianbianlan/archive/2012/01/19/164364.html</link><dc:creator>天边蓝</dc:creator><author>天边蓝</author><pubDate>Thu, 19 Jan 2012 03:39:00 GMT</pubDate><guid>http://www.cppblog.com/tianbianlan/archive/2012/01/19/164364.html</guid><wfw:comment>http://www.cppblog.com/tianbianlan/comments/164364.html</wfw:comment><comments>http://www.cppblog.com/tianbianlan/archive/2012/01/19/164364.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/tianbianlan/comments/commentRss/164364.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/tianbianlan/services/trackbacks/164364.html</trackback:ping><description><![CDATA[<h3>
<h1></h1>
<p style="line-height: 130%"><span style="font-size: small"><span style="font-family: 宋体">转载来源：<a href="http://blog.csdn.net/dragonbooker/article/details/6173321">http://blog.csdn.net/dragonbooker/article/details/6173321</a><br />大端模式</span></span></p>
<p style="line-height: 130%"><span style="font-size: small"><span style="font-family: 宋体">　　所谓的大端模式，是指数据的低位（就是权值较小的后面那几位）保存在内存的高地址中，而数据的高位，保存在内存的低地址中，这样的存储模式有点儿类似于把数据当作字符串顺序处理：地址由小向大增加，而数据从高位往低位放；</span> </span></p>
<p style="line-height: 130%" sizset="34" sizcache="1"><a name="1_2"></a>&nbsp;</p>
<p style="line-height: 130%"><span style="font-size: small"><span style="font-family: 宋体">小端模式</span></span></p>
<p style="line-height: 130%"><span style="font-size: small"><span style="font-family: 宋体">　　所谓的小端模式，是指数据的低位保存在内存的低地址中，而数</span> <span style="font-family: 宋体">据的高位保存在内存的高地址中，这种存储模式将地址的高低和数据位权有效地结合起来，高地址部分权值高，低地址部分权值低，和我们的逻辑方法一致。</span> </span></p>
<p style="line-height: 130%" sizset="35" sizcache="1"><a name="1_3"></a>&nbsp;</p>
<p style="line-height: 130%"><span style="font-size: small"><span style="font-family: 宋体">为什么有大小端模式之分</span></span></p>
<p style="text-indent: 21pt; line-height: 130%"><span style="font-size: small"><span style="font-family: 宋体">为什么会有大小端模式之分呢？这是因为在计算机系统中，我们是以字节为单位的，每个地址单元都对应着一个字节，一个字节为</span><span style="font-family: Times New Roman"> 8bit</span><span style="font-family: 宋体">。但是在</span><span style="font-family: Times New Roman">C</span><span style="font-family: 宋体">语言中除了</span><span style="font-family: Times New Roman">8bit</span><span style="font-family: 宋体">的</span><span style="font-family: Times New Roman">char</span><span style="font-family: 宋体">之外，还有</span><span style="font-family: Times New Roman">16bit</span><span style="font-family: 宋体">的</span><span style="font-family: Times New Roman">short</span><span style="font-family: 宋体">型，</span><span style="font-family: Times New Roman">32bit</span><span style="font-family: 宋体">的</span><span style="font-family: Times New Roman">long</span><span style="font-family: 宋体">型（要看具体的编译器），另外，对于位数大于</span><span style="font-family: Times New Roman"> 8</span><span style="font-family: 宋体">位的处理器，例如</span><span style="font-family: Times New Roman">16</span><span style="font-family: 宋体">位或者</span><span style="font-family: Times New Roman">32</span><span style="font-family: 宋体">位的处理器，由于寄存器宽度大于一个字节，那么必然存在着一个如何将多个字节安排的问题。因此就导致了大端存储模式和小端存储模式。例如一个</span><span style="font-family: Times New Roman">16bit</span><span style="font-family: 宋体">的</span><span style="font-family: Times New Roman">short</span><span style="font-family: 宋体">型</span><span style="font-family: Times New Roman">x</span><span style="font-family: 宋体">，在内存中的地址为</span><span style="font-family: Times New Roman">0x0010</span><span style="font-family: 宋体">，</span><span style="font-family: Times New Roman">x</span><span style="font-family: 宋体">的值为</span><span style="font-family: Times New Roman">0x1122</span><span style="font-family: 宋体">，那么</span><span style="font-family: Times New Roman">0x11</span><span style="font-family: 宋体">为高字节，</span><span style="font-family: Times New Roman">0x22</span><span style="font-family: 宋体">为低字节。对于</span> <span style="font-family: 宋体">大端模式，就将</span><span style="font-family: Times New Roman">0x11</span><span style="font-family: 宋体">放在低地址中，即</span><span style="font-family: Times New Roman">0x0010</span><span style="font-family: 宋体">中，</span><span style="font-family: Times New Roman">0x22</span><span style="font-family: 宋体">放在高地址中，即</span><span style="font-family: Times New Roman">0x0011</span><span style="font-family: 宋体">中。小端模式，刚好相反。我们常用的</span><span style="font-family: Times New Roman">X86</span><span style="font-family: 宋体">结构是小端模式，而</span><span style="font-family: Times New Roman">KEIL C51</span><span style="font-family: 宋体">则为大端模式。很多的</span><span style="font-family: Times New Roman">ARM</span><span style="font-family: 宋体">，</span><span style="font-family: Times New Roman">DSP</span><span style="font-family: 宋体">都为小端模式。有些</span><span style="font-family: Times New Roman">ARM</span><span style="font-family: 宋体">处理器还可以由硬件来选择是大端模式还是小端模式。</span></span></p>
<h3><span style="font-family: 宋体"><span style="font-size: large">二、举例说明</span></span></h3>
<p style="line-height: 130%"><span style="font-size: small"><span style="font-family: 宋体">大家都知道字符&#8216;</span><span style="font-family: Times New Roman">A</span><span style="font-family: 宋体">&#8217;的</span><span style="font-family: Times New Roman">ASCII</span><span style="font-family: 宋体">码值为</span><span style="font-family: Times New Roman">65</span><span style="font-family: 宋体">（十进制）也就是</span><span style="font-family: Times New Roman">0x41</span><span style="font-family: 宋体">，那么这个值在不同大小端模式的系统中存放的方式分别为：</span></span></p>
<p style="line-height: 130%"><span style="font-size: small"><span style="font-family: 宋体">大端模式：</span><span style="font-family: Times New Roman">00 00 00 41&nbsp;-----</span><span style="font-family: 宋体">高低模式</span></span></p>
<p style="line-height: 130%"><span style="font-size: small"><span style="font-family: 宋体">小端模式：</span><span style="font-family: Times New Roman">41 00 00 00 &nbsp;-----</span><span style="font-family: 宋体">低低模式</span></span></p>
<h3><span style="font-family: 宋体"><span style="font-size: large">三、使用代码判断大小端模式</span></span></h3>
<p><span style="font-size: small"><span style="font-family: 宋体">可以通过声明一个联合（</span><span style="font-family: Times New Roman">union</span><span style="font-family: 宋体">）判断大小端模式：</span></span></p>
<p>&nbsp;</p>
<p><span style="font-size: small; font-family: Times New Roman">/**</span></p>
<p><span style="font-size: small"><span style="font-family: Times New Roman">&nbsp;* </span><span style="font-family: 宋体">方法一</span> <span style="font-family: 宋体">得到当前系统的大小端属性</span><span style="font-family: Times New Roman">, </span><span style="font-family: 宋体">此方法要保证在</span><span style="font-family: Times New Roman">32</span><span style="font-family: 宋体">位机测试</span></span></p>
<p><span style="font-family: Times New Roman"><span style="font-size: small">&nbsp;*/</span></span></p>
<p><span style="font-size: small; font-family: Times New Roman">static union { </span></p>
<p><span style="font-family: Times New Roman"><span style="font-size: small"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; char c[4]; </span></span></span></p>
<p><span style="font-family: Times New Roman"><span style="font-size: small"><span>&nbsp;&nbsp;&nbsp; unsigned long l; </span></span></span></p>
<p><span style="font-size: small; font-family: Times New Roman">} </span></p>
<p>&nbsp;</p>
<p><span style="font-size: small"><span style="font-family: Times New Roman">endian_test = { { 'l', '?', '?', 'b' } }; </span><span style="font-family: 宋体">　　</span></span></p>
<p>&nbsp;</p>
<p><span style="font-size: small; font-family: Times New Roman">#define ENDIANNESS ((char)endian_test.l)</span></p>
<p>&nbsp;</p>
<p><span style="font-size: small; font-family: Times New Roman">/**</span></p>
<p><span style="font-size: small"><span style="font-family: Times New Roman">&nbsp;* </span><span style="font-family: 宋体">方法二</span><span style="font-family: Times New Roman">: </span><span style="font-family: 宋体">得到当前系统的大小端属性</span></span></p>
<p><span style="font-family: Times New Roman"><span style="font-size: small">&nbsp;*/</span></span></p>
<p><span style="font-size: small; font-family: Times New Roman">static union {</span></p>
<p><span style="font-family: Times New Roman"><span style="font-size: small"><span>&nbsp;&nbsp;&nbsp;&nbsp; short n;</span></span></span></p>
<p><span style="font-family: Times New Roman"><span style="font-size: small"><span>&nbsp;&nbsp;&nbsp;&nbsp; char c[sizeof(short)];</span></span></span></p>
<p><span style="font-size: small; font-family: Times New Roman">}un;</span></p>
<p>&nbsp;</p>
<p><span style="font-size: small; font-family: Times New Roman">int getEndian()</span></p>
<p><span style="font-size: small; font-family: Times New Roman">{</span></p>
<p><span style="font-family: Times New Roman"><span style="font-size: small"><span>&nbsp;&nbsp; un.n = 0x0102;</span></span></span></p>
<p><span>&nbsp;</span></p>
<p><span style="font-family: Times New Roman"><span style="font-size: small"><span>&nbsp;&nbsp; if ((un.c[0] == 1 &amp;&amp; un.c[1] == 2))</span></span></span></p>
<p><span style="font-family: Times New Roman"><span style="font-size: small"><span>&nbsp;&nbsp; {</span></span></span></p>
<p><span style="font-family: Times New Roman"><span style="font-size: small"><span>&nbsp;&nbsp;&nbsp;&nbsp; printf("big endian/n");</span></span></span></p>
<p><span style="font-family: Times New Roman"><span style="font-size: small"><span>&nbsp;&nbsp; }</span></span></span></p>
<p><span style="font-family: Times New Roman"><span style="font-size: small"><span>&nbsp;&nbsp; else if ((un.c[0] == 2 &amp;&amp; un.c[1] == 1))</span></span></span></p>
<p><span style="font-family: Times New Roman"><span style="font-size: small"><span>&nbsp;&nbsp; {</span></span></span></p>
<p><span style="font-family: Times New Roman"><span style="font-size: small"><span>&nbsp;&nbsp;&nbsp;&nbsp; printf("little endian/n");</span></span></span></p>
<p><span style="font-family: Times New Roman"><span style="font-size: small"><span>&nbsp;&nbsp; }</span></span></span></p>
<p><span style="font-family: Times New Roman"><span style="font-size: small"><span>&nbsp;&nbsp; else </span></span></span></p>
<p><span style="font-family: Times New Roman"><span style="font-size: small"><span>&nbsp;&nbsp;&nbsp;&nbsp; printf("error!/n");</span></span></span></p>
<p>&nbsp;</p>
<p><span style="font-family: Times New Roman"><span style="font-size: small"><span>&nbsp;&nbsp; return 0;</span></span></span></p>
<p><span style="font-size: small; font-family: Times New Roman">}</span></p>
<p>&nbsp;</p>
<p><span style="font-size: small; font-family: Times New Roman">/**</span></p>
<p><span style="font-size: small"><span style="font-family: Times New Roman">&nbsp;* </span><span style="font-family: 宋体">方法三</span><span style="font-family: Times New Roman">: </span><span style="font-family: 宋体">得到当前系统的大小端属性</span></span></p>
<p><span style="font-family: Times New Roman"><span style="font-size: small">&nbsp;*/</span></span></p>
<p><span style="font-size: small; font-family: Times New Roman">int getEndian()</span></p>
<p><span style="font-size: small; font-family: Times New Roman">{</span></p>
<p><span style="font-family: Times New Roman"><span style="font-size: small"><span>&nbsp;&nbsp; int c = 1;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // big-endian: 00 00 00 01 little-endian: 01 00 00 00</span></span></span></p>
<p>&nbsp;&nbsp;<span style="font-size: small"><span style="font-family: Times New Roman">// int c = 0x02000001;&nbsp;</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="font-size: small; font-family: Times New Roman">// big-endian: 02 00 00 01 little-endian: 01 00 00 02</span></span></p>
<p>&nbsp;</p>
<p><span style="font-size: small"><span style="font-family: Times New Roman"><span>&nbsp;&nbsp; if ((*(char *)&amp;c) == 1)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // </span></span><span style="font-family: 宋体">取</span><span style="font-family: Times New Roman">c</span><span style="font-family: 宋体">变量所在地址上的一个字节。</span></span></p>
<p><span style="font-size: small"><span style="font-family: Times New Roman"><span>&nbsp;&nbsp; {</span></span></span></p>
<p><span style="font-size: small"><span style="font-family: Times New Roman"><span>&nbsp;&nbsp;&nbsp;&nbsp; printf("little endian/n");</span></span></span></p>
<p><span style="font-size: small"><span style="font-family: Times New Roman"><span>&nbsp;&nbsp; }</span></span></span></p>
<p><span style="font-size: small"><span style="font-family: Times New Roman"><span>&nbsp;&nbsp; else</span></span></span></p>
<p><span style="font-size: small"><span style="font-family: Times New Roman"><span>&nbsp;&nbsp;&nbsp;&nbsp; printf("big endian");</span></span></span></p>
<p>&nbsp;</p>
<p><span style="font-size: small"><span style="font-family: Times New Roman"><span>&nbsp;&nbsp; return 0;</span></span></span></p>
<p><span style="font-size: small; font-family: Times New Roman">}</span></p><a name="1_1"></a></h3><img src ="http://www.cppblog.com/tianbianlan/aggbug/164364.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/tianbianlan/" target="_blank">天边蓝</a> 2012-01-19 11:39 <a href="http://www.cppblog.com/tianbianlan/archive/2012/01/19/164364.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>【转】TCP三次握手/四次挥手详解 </title><link>http://www.cppblog.com/tianbianlan/archive/2012/01/11/164020.html</link><dc:creator>天边蓝</dc:creator><author>天边蓝</author><pubDate>Wed, 11 Jan 2012 15:49:00 GMT</pubDate><guid>http://www.cppblog.com/tianbianlan/archive/2012/01/11/164020.html</guid><wfw:comment>http://www.cppblog.com/tianbianlan/comments/164020.html</wfw:comment><comments>http://www.cppblog.com/tianbianlan/archive/2012/01/11/164020.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/tianbianlan/comments/commentRss/164020.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/tianbianlan/services/trackbacks/164020.html</trackback:ping><description><![CDATA[来源：<a href="http://blog.csdn.net/sfwork/article/details/6876692">http://blog.csdn.net/sfwork/article/details/6876692</a><br />1<wbr>、建立连接协议（三次握手）<wbr><br />（1）客户端发送一个带SYN标志的TCP报文到服务器。这是三次握手过程中的报文1。<br />（2） 服务器端回应客户端的，这是三次握手中的第2个报文，这个报文同时带ACK标志和SYN标志。因此它表示对刚才客户端SYN报文的回应；同时又标志SYN给客户端，询问客户端是否准备好进行数据通讯。<br />（3） 客户必须再次回应服务段一个ACK报文，这是报文段3。<br />2<wbr>、连接终止协议（四次挥手）<wbr><br />　 　由于TCP连接是全双工的，因此每个方向都必须单独进行关闭。这原则是当一方完成它的数据发送任务后就能发送一个FIN来终止这个方向的连接。收到一个 FIN只意味着这一方向上没有数据流动，一个TCP连接在收到一个FIN后仍能发送数据。首先进行关闭的一方将执行主动关闭，而另一方执行被动关闭。<br />　（1） TCP客户端发送一个FIN，用来关闭客户到服务器的数据传送（报文段4）。<br />　（2） 服务器收到这个FIN，它发回一个ACK，确认序号为收到的序号加1（报文段5）。和SYN一样，一个FIN将占用一个序号。<br />　（3） 服务器关闭客户端的连接，发送一个FIN给客户端（报文段6）。<br />　（4） 客户段发回ACK报文确认，并将确认序号设置为收到序号加1（报文段7）。<br />CLOSED: 这个没什么好说的了，表示初始状态。<br />LISTEN: 这个也是非常容易理解的一个状态，表示服务器端的某个SOCKET处于监听状态，可以接受连接了。<br />SYN_RCVD: 这个状态表示接受到了SYN报文，在正常情况下，这个状态是服务器端的SOCKET在建立TCP连接时的三次握手会话过程中的一个中间状态，很短暂，基本上用netstat你是很难看到这种状态的，除非你特意写了一个客户端测试程序，故意将三次TCP握手过程中最后一个ACK报文不予发送。因此这种状态时，当收到客户端的ACK报文后，它会进入到ESTABLISHED状态。<br />SYN_SENT: 这个状态与SYN_RCVD遥想呼应，当客户端SOCKET执行CONNECT连接时，它首先发送SYN报文，因此也随即它会进入到了SYN_SENT状态，并等待服务端的发送三次握手中的第2个报文。SYN_SENT状态表示客户端已发送SYN报文。<br />ESTABLISHED：这个容易理解了，表示连接已经建立了。<br />FIN_WAIT_1: 这个状态要好好解释一下，其实FIN_WAIT_1和FIN_WAIT_2状态的真正含义都是表示等待对方的FIN报文。而这两种状态的区别是：FIN_WAIT_1状态实际上是当SOCKET在ESTABLISHED状态时，它想主动关闭连接，向对方发送了FIN报文，此时该SOCKET即进入到FIN_WAIT_1状态。而当对方回应ACK报文后，则进入到FIN_WAIT_2状态，当然在实际的正常情况下，无论对方何种情况下，都应该马上回应ACK报文，所以FIN_WAIT_1状态一般是比较难见到的，而FIN_WAIT_2状态还有时常常可以用netstat看到。<br />FIN_WAIT_2：上面已经详细解释了这种状态，实际上FIN_WAIT_2状态下的SOCKET，表示半连接，也即有一方要求close连接，但另外还告诉对方，我暂时还有点数据需要传送给你，稍后再关闭连接。<br />TIME_WAIT: 表示收到了对方的FIN报文，并发送出了ACK报文，就等2MSL后即可回到CLOSED可用状态了。如果FIN_WAIT_1状态下，收到了对方同时带FIN标志和ACK标志的报文时，可以直接进入到TIME_WAIT状态，而无须经过FIN_WAIT_2状态。<br />CLOSING: 这种状态比较特殊，实际情况中应该是很少见，属于一种比较罕见的例外状态。正常情况下，当你发送FIN报文后，按理来说是应该先收到（或同时收到）对方的ACK报文，再收到对方的FIN报文。但是CLOSING状态表示你发送FIN报文后，并没有收到对方的ACK报文，反而却也收到了对方的FIN报文。什么情况下会出现此种情况呢？其实细想一下，也不难得出结论：那就是如果双方几乎在同时close一个SOCKET的话，那么就出现了双方同时发送FIN报文的情况，也即会出现CLOSING状态，表示双方都正在关闭SOCKET连接。<br />CLOSE_WAIT: 这种状态的含义其实是表示在等待关闭。怎么理解呢？当对方close一个SOCKET后发送FIN报文给自己，你系统毫无疑问地会回应一个ACK报文给对方，此时则进入到CLOSE_WAIT状态。接下来呢，实际上你真正需要考虑的事情是察看你是否还有数据发送给对方，如果没有的话，那么你也就可以close这个SOCKET，发送FIN报文给对方，也即关闭连接。所以你在CLOSE_WAIT状态下，需要完成的事情是等待你去关闭连接。<br />LAST_ACK: 这个状态还是比较容易好理解的，它是被动关闭一方在发送FIN报文后，最后等待对方的ACK报文。当收到ACK报文后，也即可以进入到CLOSED可用状态了。<br />最后有2个问题的回答，我自己分析后的结论（不一定保证100%正确）<br />1、 为什么建立连接协议是三次握手，而关闭连接却是四次握手呢？<br />这是因为服务端的LISTEN状态下的SOCKET当收到SYN报文的建连请求后，它可以把ACK和SYN（ACK起应答作用，而SYN起同步作用）放在一个报文里来发送。但关闭连接时，当收到对方的FIN报文通知时，它仅仅表示对方没有数据发送给你了；但未必你所有的数据都全部发送给对方了，所以你可以未必会马上会关闭SOCKET,也即你可能还需要发送一些数据给对方之后，再发送FIN报文给对方来表示你同意现在可以关闭连接了，所以它这里的ACK报文和FIN报文多数情况下都是分开发送的。<br />2、 为什么TIME_WAIT状态还需要等2MSL后才能返回到CLOSED状态？<br />这是因为：虽然双方都同意关闭连接了，而且握手的4个报文也都协调和发送完毕，按理可以直接回到CLOSED状态（就好比从SYN_SEND状态到ESTABLISH状态那样）；但是因为我们必须要假想网络是不可靠的，你无法保证你最后发送的ACK报文会一定被对方收到，因此对方处于LAST_ACK状态下的SOCKET可能会因为超时未收到ACK报文，而重发FIN报文，所以这个TIME_WAIT状态的作用就是用来重发可能丢失的ACK报文。<img src ="http://www.cppblog.com/tianbianlan/aggbug/164020.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/tianbianlan/" target="_blank">天边蓝</a> 2012-01-11 23:49 <a href="http://www.cppblog.com/tianbianlan/archive/2012/01/11/164020.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>B+数的实现--优秀代码</title><link>http://www.cppblog.com/tianbianlan/archive/2011/11/08/159814.html</link><dc:creator>天边蓝</dc:creator><author>天边蓝</author><pubDate>Tue, 08 Nov 2011 04:32:00 GMT</pubDate><guid>http://www.cppblog.com/tianbianlan/archive/2011/11/08/159814.html</guid><wfw:comment>http://www.cppblog.com/tianbianlan/comments/159814.html</wfw:comment><comments>http://www.cppblog.com/tianbianlan/archive/2011/11/08/159814.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/tianbianlan/comments/commentRss/159814.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/tianbianlan/services/trackbacks/159814.html</trackback:ping><description><![CDATA[优秀代码<br />http://idlebox.net/2007/stx-btree/<br /><img src ="http://www.cppblog.com/tianbianlan/aggbug/159814.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/tianbianlan/" target="_blank">天边蓝</a> 2011-11-08 12:32 <a href="http://www.cppblog.com/tianbianlan/archive/2011/11/08/159814.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转]C++ 对象的内存布局 </title><link>http://www.cppblog.com/tianbianlan/archive/2010/04/29/113987.html</link><dc:creator>天边蓝</dc:creator><author>天边蓝</author><pubDate>Thu, 29 Apr 2010 11:30:00 GMT</pubDate><guid>http://www.cppblog.com/tianbianlan/archive/2010/04/29/113987.html</guid><wfw:comment>http://www.cppblog.com/tianbianlan/comments/113987.html</wfw:comment><comments>http://www.cppblog.com/tianbianlan/archive/2010/04/29/113987.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/tianbianlan/comments/commentRss/113987.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/tianbianlan/services/trackbacks/113987.html</trackback:ping><description><![CDATA[<div>
<div align=center>2008-11-14 作者：陈皓 来源：csdn</div>
<p><strong><br>前言</strong></p>
<p>07年12月，我写了一篇《C++虚函数表解析》的文章，引起了大家的兴趣。有很多朋友对我的文章留了言，有鼓励我的，有批评我的，还有很多问问题的。我在这里一并对大家的留言表示感谢。这也是我为什么再写一篇续言的原因。因为，在上一篇文章中，我用了的示例都是非常简单的，主要是为了说明一些机理上的问题，也是为了图一些表达上方便和简单。不想，这篇文章成为了打开C++对象模型内存布局的一个引子，引发了大家对C++对象的更深层次的讨论。当然，我之前的文章还有很多方面没有涉及，从我个人感觉下来，在谈论虚函数表里，至少有以下这些内容没有涉及：</p>
<p>1）有成员变量的情况。</p>
<p>2）有重复继承的情况。</p>
<p>3）有虚拟继承的情况。</p>
<p>4）有钻石型虚拟继承的情况。</p>
<p>这些都是我本篇文章需要向大家说明的东西。所以，这篇文章将会是《C++虚函数表解析》的一个续篇，也是一篇高级进阶的文章。我希望大家在读这篇文章之前对C++有一定的基础和了解，并能先读我的上一篇文章。因为这篇文章的深度可能会比较深，而且会比较杂乱，我希望你在读本篇文章时不会有大脑思维紊乱导致大脑死机的情况。;-)</p>
<p>对象的影响因素</p>
<p>简而言之，我们一个类可能会有如下的影响因素：</p>
<p>1）成员变量</p>
<p>2）虚函数（产生虚函数表）</p>
<p>3）单一继承（只继承于一个类）</p>
<p>4）多重继承（继承多个类）</p>
<p>5）重复继承（继承的多个父类中其父类有相同的超类）</p>
<p>6）虚拟继承（使用virtual方式继承，为了保证继承后父类的内存布局只会存在一份）</p>
<p>上述的东西通常是C++这门语言在语义方面对对象内部的影响因素，当然，还会有编译器的影响（比如优化），还有字节对齐的影响。在这里我们都不讨论，我们只讨论C++语言上的影响。</p>
<p>本篇文章着重讨论下述几个情况下的C++对象的内存布局情况。</p>
<p>1）单一的一般继承（带成员变量、虚函数、虚函数覆盖）</p>
<p>2）单一的虚拟继承（带成员变量、虚函数、虚函数覆盖）</p>
<p>3）多重继承（带成员变量、虚函数、虚函数覆盖）</p>
<p>4）重复多重继承（带成员变量、虚函数、虚函数覆盖）</p>
<p>5）钻石型的虚拟多重继承（带成员变量、虚函数、虚函数覆盖）</p>
<p>我们的目标就是，让事情越来越复杂。</p>
<p><strong>知识复习</strong></p>
<p>我们简单地复习一下，我们可以通过对象的地址来取得虚函数表的地址，如：</p>
<p>typedef void(*Fun)(void);</p>
<p>Base b;</p>
<p>Fun pFun = NULL;</p>
<p>cout &lt;&lt; "虚函数表地址：" &lt;&lt; (int*)(&amp;b) &lt;&lt; endl;</p>
<p>cout &lt;&lt; "虚函数表 — 第一个函数地址：" &lt;&lt; (int*)*(int*)(&amp;b) &lt;&lt; endl;</p>
<p>// Invoke the first virtual function </p>
<p>pFun = (Fun)*((int*)*(int*)(&amp;b));</p>
<p>pFun();</p>
<p>我们同样可以用这种方式来取得整个对象实例的内存布局。因为这些东西在内存中都是连续分布的，我们只需要使用适当的地址偏移量，我们就可以获得整个内存对象的布局。</p>
<p>本篇文章中的例程或内存布局主要使用如下编译器和系统：</p>
<p>1）Windows XP 和 VC++ 2003</p>
<p>2）Cygwin 和 G++ 3.4.4</p>
<p><strong>单一的一般继承</strong></p>
<p>下面，我们假设有如下所示的一个继承关系：</p>
<p><img src="http://www.uml.org.cn/c++/images/dd0ssss1.jpg" width=177 height=366></p>
<p>请注意，在这个继承关系中，父类，子类，孙子类都有自己的一个成员变量。而了类覆盖了父类的f()方法，孙子类覆盖了子类的g_child()及其超类的f()。</p>
<p>我们的源程序如下所示：</p>
<p>class Parent {</p>
<p>public:</p>
<p>int iparent;</p>
<p>Parent ():iparent (10) {}</p>
<p>virtual void f() { cout &lt;&lt; " Parent::f()" &lt;&lt; endl; }</p>
<p>virtual void g() { cout &lt;&lt; " Parent::g()" &lt;&lt; endl; }</p>
<p>virtual void h() { cout &lt;&lt; " Parent::h()" &lt;&lt; endl; }</p>
<p>&nbsp;</p>
<p>};</p>
<p>&nbsp;</p>
<p>class Child : public Parent {</p>
<p>public:</p>
<p>int ichild;</p>
<p>Child():ichild(100) {}</p>
<p>virtual void f() { cout &lt;&lt; "Child::f()" &lt;&lt; endl; }</p>
<p>virtual void g_child() { cout &lt;&lt; "Child::g_child()" &lt;&lt; endl; }</p>
<p>virtual void h_child() { cout &lt;&lt; "Child::h_child()" &lt;&lt; endl; }</p>
<p>};</p>
<p>&nbsp;</p>
<p>class GrandChild : public Child{</p>
<p>public:</p>
<p>int igrandchild;</p>
<p>GrandChild():igrandchild(1000) {}</p>
<p>virtual void f() { cout &lt;&lt; "GrandChild::f()" &lt;&lt; endl; }</p>
<p>virtual void g_child() { cout &lt;&lt; "GrandChild::g_child()" &lt;&lt; endl; }</p>
<p>virtual void h_grandchild() { cout &lt;&lt; "GrandChild::h_grandchild()" &lt;&lt; endl; }</p>
<p>};</p>
<p>我们使用以下程序作为测试程序：（下面程序中，我使用了一个int** pVtab 来作为遍历对象内存布局的指针，这样，我就可以方便地像使用数组一样来遍历所有的成员包括其虚函数表了，在后面的程序中，我也是用这样的方法的，请不必感到奇怪，）</p>
<p>typedef void(*Fun)(void);</p>
<p>GrandChild gc; </p>
<p>int** pVtab = (int**)&amp;gc;</p>
<p>cout &lt;&lt; "[0] GrandChild::_vptr-&gt;" &lt;&lt; endl;</p>
<p>for (int i=0; (Fun)pVtab[0][i]!=NULL; i++){</p>
<p>pFun = (Fun)pVtab[0][i];</p>
<p>cout &lt;&lt; " ["&lt;&lt;i&lt;&lt;"] ";</p>
<p>pFun();</p>
<p>}</p>
<p>cout &lt;&lt; "[1] Parent.iparent = " &lt;&lt; (int)pVtab[1] &lt;&lt; endl;</p>
<p>cout &lt;&lt; "[2] Child.ichild = " &lt;&lt; (int)pVtab[2] &lt;&lt; endl;</p>
<p>cout &lt;&lt; "[3] GrandChild.igrandchild = " &lt;&lt; (int)pVtab[3] &lt;&lt; endl;</p>
<p>其运行结果如下所示：（在VC++ 2003和G++ 3.4.4下）</p>
<table id=table1 border=1 cellSpacing=0 cellPadding=0>
    <tbody>
        <tr>
            <td vAlign=top width=420>
            <p><font color=#c0c0c0 size=2 face="Courier New"><strong>[0] GrandChild::_vptr-&gt;</strong></font></p>
            <p><font color=#c0c0c0 size=2><strong><font face="Courier New">&nbsp;&nbsp;&nbsp; [0] GrandChild::f()</font></strong></font></p>
            <p><font color=#c0c0c0 size=2><strong><font face="Courier New">&nbsp;&nbsp;&nbsp; [1] Parent::g()</font></strong></font></p>
            <p><font color=#c0c0c0 size=2><strong><font face="Courier New">&nbsp;&nbsp;&nbsp; [2] Parent::h()</font></strong></font></p>
            <p><font color=#c0c0c0 size=2><strong><font face="Courier New">&nbsp;&nbsp;&nbsp; [3] GrandChild::g_child()</font></strong></font></p>
            <p><font color=#c0c0c0 size=2><strong><font face="Courier New">&nbsp;&nbsp;&nbsp; [4] Child::h1()</font></strong></font></p>
            <p><font color=#c0c0c0 size=2><strong><font face="Courier New">&nbsp;&nbsp;&nbsp; [5] GrandChild::h_grandchild()</font></strong></font></p>
            <p><font color=#c0c0c0 size=2 face="Courier New"><strong>[1] Parent.iparent = 10</strong></font></p>
            <p><font color=#c0c0c0 size=2 face="Courier New"><strong>[2] Child.ichild = 100</strong></font></p>
            <p><strong><font color=#c0c0c0 size=2 face="Courier New">[3] GrandChild.igrandchild = 1000</font></strong></p>
            </td>
        </tr>
    </tbody>
</table>
<p>使用图片表示如下：</p>
<p><img src="http://www.uml.org.cn/c++/images/ddsssssss02.jpg" width=500 height=237></p>
<p>可见以下几个方面：</p>
<p>1）虚函数表在最前面的位置。</p>
<p>2）成员变量根据其继承和声明顺序依次放在后面。</p>
<p>3）在单一的继承中，被overwrite的虚函数在虚函数表中得到了更新。</p>
<p><strong>多重继承</strong></p>
<p>下面，再让我们来看看多重继承中的情况，假设有下面这样一个类的继承关系。注意：子类只overwrite了父类的f()函数，而还有一个是自己的函数（我们这样做的目的是为了用g1()作为一个标记来标明子类的虚函数表）。而且每个类中都有一个自己的成员变量：</p>
<p><img src="http://www.uml.org.cn/c++/images/dd03.jpg" width=328 height=265> </p>
<p>我们的类继承的源代码如下所示：父类的成员初始为10，20，30，子类的为100</p>
<p>class Base1 {</p>
<p>public:</p>
<p>int ibase1;</p>
<p>Base1():ibase1(10) {}</p>
<p>virtual void f() { cout &lt;&lt; "Base1::f()" &lt;&lt; endl; }</p>
<p>virtual void g() { cout &lt;&lt; "Base1::g()" &lt;&lt; endl; }</p>
<p>virtual void h() { cout &lt;&lt; "Base1::h()" &lt;&lt; endl; }</p>
<p>&nbsp;</p>
<p>};</p>
<p>class Base2 {</p>
<p>public:</p>
<p>int ibase2;</p>
<p>Base2():ibase2(20) {}</p>
<p>virtual void f() { cout &lt;&lt; "Base2::f()" &lt;&lt; endl; }</p>
<p>virtual void g() { cout &lt;&lt; "Base2::g()" &lt;&lt; endl; }</p>
<p>virtual void h() { cout &lt;&lt; "Base2::h()" &lt;&lt; endl; }</p>
<p>};</p>
<p>class Base3 {</p>
<p>public:</p>
<p>int ibase3;</p>
<p>Base3():ibase3(30) {}</p>
<p>virtual void f() { cout &lt;&lt; "Base3::f()" &lt;&lt; endl; }</p>
<p>virtual void g() { cout &lt;&lt; "Base3::g()" &lt;&lt; endl; }</p>
<p>virtual void h() { cout &lt;&lt; "Base3::h()" &lt;&lt; endl; }</p>
<p>};</p>
<p>class Derive : public Base1, public Base2, public Base3 {</p>
<p>public:</p>
<p>int iderive;</p>
<p>Derive():iderive(100) {}</p>
<p>virtual void f() { cout &lt;&lt; "Derive::f()" &lt;&lt; endl; }</p>
<p>virtual void g1() { cout &lt;&lt; "Derive::g1()" &lt;&lt; endl; }</p>
<p>};</p>
<p>我们通过下面的程序来查看子类实例的内存布局：下面程序中，注意我使用了一个s变量，其中用到了sizof(Base)来找下一个类的偏移量。（因为我声明的是int成员，所以是4个字节，所以没有对齐问题。关于内存的对齐问题，大家可以自行试验，我在这里就不多说了）</p>
<p>typedef void(*Fun)(void);</p>
<p>Derive d;</p>
<p>int** pVtab = (int**)&amp;d;</p>
<p>cout &lt;&lt; "[0] Base1::_vptr-&gt;" &lt;&lt; endl;</p>
<p>pFun = (Fun)pVtab[0][0];</p>
<p>cout &lt;&lt; " [0] ";</p>
<p>pFun();</p>
<p>pFun = (Fun)pVtab[0][1];</p>
<p>cout &lt;&lt; " [1] ";pFun();</p>
<p>pFun = (Fun)pVtab[0][2];</p>
<p>cout &lt;&lt; " [2] ";pFun();</p>
<p>pFun = (Fun)pVtab[0][3];</p>
<p>cout &lt;&lt; " [3] "; pFun();</p>
<p>pFun = (Fun)pVtab[0][4];</p>
<p>cout &lt;&lt; " [4] "; cout&lt;&lt;pFun&lt;&lt;endl;</p>
<p>cout &lt;&lt; "[1] Base1.ibase1 = " &lt;&lt; (int)pVtab[1] &lt;&lt; endl;</p>
<p>int s = sizeof(Base1)/4;</p>
<p>cout &lt;&lt; "[" &lt;&lt; s &lt;&lt; "] Base2::_vptr-&gt;"&lt;&lt;endl;</p>
<p>pFun = (Fun)pVtab[s][0];</p>
<p>cout &lt;&lt; " [0] "; pFun();</p>
<p>Fun = (Fun)pVtab[s][1];</p>
<p>cout &lt;&lt; " [1] "; pFun();</p>
<p>pFun = (Fun)pVtab[s][2];</p>
<p>cout &lt;&lt; " [2] "; pFun(); </p>
<p>pFun = (Fun)pVtab[s][3];</p>
<p>out &lt;&lt; " [3] ";</p>
<p>cout&lt;&lt;pFun&lt;&lt;endl;</p>
<p>cout &lt;&lt; "["&lt;&lt; s+1 &lt;&lt;"] Base2.ibase2 = " &lt;&lt; (int)pVtab[s+1] &lt;&lt; endl;</p>
<p>s = s + sizeof(Base2)/4;</p>
<p>cout &lt;&lt; "[" &lt;&lt; s &lt;&lt; "] Base3::_vptr-&gt;"&lt;&lt;endl;</p>
<p>pFun = (Fun)pVtab[s][0];</p>
<p>cout &lt;&lt; " [0] "; pFun();</p>
<p>&nbsp;</p>
<p>pFun = (Fun)pVtab[s][1];</p>
<p>cout &lt;&lt; " [1] "; pFun();</p>
<p>pFun = (Fun)pVtab[s][2];</p>
<p>cout &lt;&lt; " [2] "; pFun(); </p>
<p>&nbsp;</p>
<p>pFun = (Fun)pVtab[s][3];</p>
<p>cout &lt;&lt; " [3] ";</p>
<p>cout&lt;&lt;pFun&lt;&lt;endl;</p>
<p>s++;</p>
<p>cout &lt;&lt; "["&lt;&lt; s &lt;&lt;"] Base3.ibase3 = " &lt;&lt; (int)pVtab[s] &lt;&lt; endl;</p>
<p>s++;</p>
<p>cout &lt;&lt; "["&lt;&lt; s &lt;&lt;"] Derive.iderive = " &lt;&lt; (int)pVtab[s] &lt;&lt; endl;</p>
<p>其运行结果如下所示：（在VC++ 2003和G++ 3.4.4下）</p>
<table id=table1 border=1 cellSpacing=0 cellPadding=0>
    <tbody>
        <tr>
            <td vAlign=top width=432>
            <p><font color=#c0c0c0 size=2 face="Courier New"><strong>[0] Base1::_vptr-&gt;</strong></font></p>
            <p><font color=#c0c0c0 size=2 face="Courier New"><strong>&nbsp;&nbsp;&nbsp;&nbsp; [0] Derive::f()</strong></font></p>
            <p><font color=#c0c0c0 size=2 face="Courier New"><strong>&nbsp;&nbsp;&nbsp;&nbsp; [1] Base1::g()</strong></font></p>
            <p><font color=#c0c0c0 size=2 face="Courier New"><strong>&nbsp;&nbsp;&nbsp;&nbsp; [2] Base1::h()</strong></font></p>
            <p><font color=#c0c0c0 size=2 face="Courier New"><strong>&nbsp;&nbsp;&nbsp;&nbsp; [3] Driver::g1()</strong></font></p>
            <p><font size=2><strong><font color=#c0c0c0 face="Courier New">&nbsp;&nbsp;&nbsp;&nbsp; [4] 00000000&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font><font size=+0><span>&#231;</span><span><font face="Courier New"> </font></span><span>注意：在</span><span><font face="Courier New">GCC</font></span><span>下，这里是</span><span><font face="Courier New">1</font></span></font></strong></font></p>
            <p><font color=#c0c0c0 size=2 face="Courier New"><strong>[1] Base1.ibase1 = 10</strong></font></p>
            <p><font color=#c0c0c0 size=2 face="Courier New"><strong>[2] Base2::_vptr-&gt;</strong></font></p>
            <p><font color=#c0c0c0 size=2 face="Courier New"><strong>&nbsp;&nbsp;&nbsp;&nbsp; [0] Derive::f()</strong></font></p>
            <p><font color=#c0c0c0 size=2 face="Courier New"><strong>&nbsp;&nbsp;&nbsp;&nbsp; [1] Base2::g()</strong></font></p>
            <p><font color=#c0c0c0 size=2 face="Courier New"><strong>&nbsp;&nbsp;&nbsp;&nbsp; [2] Base2::h()</strong></font></p>
            <p><font size=2><strong><font color=#c0c0c0 face="Courier New">&nbsp;&nbsp;&nbsp;&nbsp; [3] 00000000&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font><font size=+0><span>&#231;</span><span><font face="Courier New"> </font></span><span>注意：在</span><span><font face="Courier New">GCC</font></span><span>下，这里是</span><span><font face="Courier New">1</font></span></font></strong></font></p>
            <p><font color=#c0c0c0 size=2 face="Courier New"><strong>[3] Base2.ibase2 = 20</strong></font></p>
            <p><font color=#c0c0c0 size=2 face="Courier New"><strong>[4] Base3::_vptr-&gt;</strong></font></p>
            <p><font color=#c0c0c0 size=2><strong><font face="Courier New">&nbsp;&nbsp;&nbsp;&nbsp; [0] Derive::f()</font></strong></font></p>
            <p><font color=#c0c0c0 size=2><strong><font face="Courier New">&nbsp;&nbsp;&nbsp;&nbsp; [1] Base3::g()</font></strong></font></p>
            <p><font color=#c0c0c0 size=2><strong><font face="Courier New">&nbsp;&nbsp;&nbsp;&nbsp; [2] Base3::h()</font></strong></font></p>
            <p><font color=#c0c0c0 size=2><strong><font face="Courier New">&nbsp;&nbsp;&nbsp;&nbsp; [3] 00000000</font></strong></font></p>
            <p><font color=#c0c0c0 size=2 face="Courier New"><strong>[5] Base3.ibase3 = 30</strong></font></p>
            <p><strong><font color=#c0c0c0 size=2 face="Courier New">[6] Derive.iderive = 100</font></strong></p>
            </td>
        </tr>
    </tbody>
</table>
<p>使用图片表示是下面这个样子：</p>
<p><img src="http://www.uml.org.cn/c++/images/dd04.jpg" width=500 height=287></p>
<p>我们可以看到：</p>
<p>1） 每个父类都有自己的虚表。</p>
<p>2） 子类的成员函数被放到了第一个父类的表中。</p>
<p>3） 内存布局中，其父类布局依次按声明顺序排列。</p>
<p>4） 每个父类的虚表中的f()函数都被overwrite成了子类的f()。这样做就是为了解决不同的父类类型的指针指向同一个子类实例，而能够调用到实际的函数。</p>
<p><strong>重复继承</strong><br></p>
<p>下面我们再来看看，发生重复继承的情况。所谓重复继承，也就是某个基类被间接地重复继承了多次。</p>
<p>下图是一个继承图，我们重载了父类的f()函数。</p>
<p><img src="http://www.uml.org.cn/c++/images/dd05.jpg" width=253 height=393></p>
<p>其类继承的源代码如下所示。其中，每个类都有两个变量，一个是整形（4字节），一个是字符（1字节），而且还有自己的虚函数，自己overwrite父类的虚函数。如子类D中，f()覆盖了超类的函数， f1() 和f2() 覆盖了其父类的虚函数，Df()为自己的虚函数。</p>
<p>class B</p>
<p>{</p>
<p>public:</p>
<p>int ib;</p>
<p>char cb;</p>
<p>public:</p>
<p>B():ib(0),cb('B') {}</p>
<p>virtual void f() { cout &lt;&lt; "B::f()" &lt;&lt; endl;}</p>
<p>virtual void Bf() { cout &lt;&lt; "B::Bf()" &lt;&lt; endl;}</p>
<p>};</p>
<p>class B1 : public B</p>
<p>{</p>
<p>public:</p>
<p>int ib1;</p>
<p>char cb1;</p>
<p>public:</p>
<p>B1():ib1(11),cb1('1') {}</p>
<p>virtual void f() { cout &lt;&lt; "B1::f()" &lt;&lt; endl;}</p>
<p>virtual void f1() { cout &lt;&lt; "B1::f1()" &lt;&lt; endl;}</p>
<p>virtual void Bf1() { cout &lt;&lt; "B1::Bf1()" &lt;&lt; endl;}</p>
<p>};</p>
<p>class B2: public B</p>
<p>{</p>
<p>public:</p>
<p>int ib2;</p>
<p>char cb2;</p>
<p>public:</p>
<p>B2():ib2(12),cb2('2') {}</p>
<p>virtual void f() { cout &lt;&lt; "B2::f()" &lt;&lt; endl;}</p>
<p>virtual void f2() { cout &lt;&lt; "B2::f2()" &lt;&lt; endl;}</p>
<p>virtual void Bf2() { cout &lt;&lt; "B2::Bf2()" &lt;&lt; endl;}</p>
<p>};</p>
<p>class D : public B1, public B2</p>
<p>{</p>
<p>public:</p>
<p>int id;</p>
<p>char cd;</p>
<p>public:</p>
<p>D():id(100),cd('D') {}</p>
<p>virtual void f() { cout &lt;&lt; "D::f()" &lt;&lt; endl;}</p>
<p>virtual void f1() { cout &lt;&lt; "D::f1()" &lt;&lt; endl;}</p>
<p>virtual void f2() { cout &lt;&lt; "D::f2()" &lt;&lt; endl;}</p>
<p>virtual void Df() { cout &lt;&lt; "D::Df()" &lt;&lt; endl;}</p>
<p>};</p>
<p>我们用来存取子类内存布局的代码如下所示：（在VC++ 2003和G++ 3.4.4下）</p>
<p>typedef void(*Fun)(void);</p>
<p>int** pVtab = NULL;</p>
<p>Fun pFun = NULL;</p>
<p>D d;</p>
<p>pVtab = (int**)&amp;d;</p>
<p>cout &lt;&lt; "[0] D::B1::_vptr-&gt;" &lt;&lt; endl;</p>
<p>pFun = (Fun)pVtab[0][0];</p>
<p>cout &lt;&lt; " [0] "; pFun();</p>
<p>pFun = (Fun)pVtab[0][1];</p>
<p>cout &lt;&lt; " [1] "; pFun();</p>
<p>pFun = (Fun)pVtab[0][2];</p>
<p>cout &lt;&lt; " [2] "; pFun();</p>
<p>pFun = (Fun)pVtab[0][3];</p>
<p>cout &lt;&lt; " [3] "; pFun();</p>
<p>pFun = (Fun)pVtab[0][4];</p>
<p>cout &lt;&lt; " [4] "; pFun();</p>
<p>pFun = (Fun)pVtab[0][5];</p>
<p>cout &lt;&lt; " [5] 0x" &lt;&lt; pFun &lt;&lt; endl;</p>
<p>cout &lt;&lt; "[1] B::ib = " &lt;&lt; (int)pVtab[1] &lt;&lt; endl;</p>
<p>cout &lt;&lt; "[2] B::cb = " &lt;&lt; (char)pVtab[2] &lt;&lt; endl;</p>
<p>cout &lt;&lt; "[3] B1::ib1 = " &lt;&lt; (int)pVtab[3] &lt;&lt; endl;</p>
<p>cout &lt;&lt; "[4] B1::cb1 = " &lt;&lt; (char)pVtab[4] &lt;&lt; endl;</p>
<p>cout &lt;&lt; "[5] D::B2::_vptr-&gt;" &lt;&lt; endl;</p>
<p>pFun = (Fun)pVtab[5][0];</p>
<p>cout &lt;&lt; " [0] "; pFun();</p>
<p>pFun = (Fun)pVtab[5][1];</p>
<p>cout &lt;&lt; " [1] "; pFun();</p>
<p>pFun = (Fun)pVtab[5][2];</p>
<p>cout &lt;&lt; " [2] "; pFun();</p>
<p>pFun = (Fun)pVtab[5][3];</p>
<p>cout &lt;&lt; " [3] "; pFun();</p>
<p>pFun = (Fun)pVtab[5][4];</p>
<p>cout &lt;&lt; " [4] 0x" &lt;&lt; pFun &lt;&lt; endl;</p>
<p>cout &lt;&lt; "[6] B::ib = " &lt;&lt; (int)pVtab[6] &lt;&lt; endl;</p>
<p>cout &lt;&lt; "[7] B::cb = " &lt;&lt; (char)pVtab[7] &lt;&lt; endl; </p>
<p>cout &lt;&lt; "[8] B2::ib2 = " &lt;&lt; (int)pVtab[8] &lt;&lt; endl;</p>
<p>cout &lt;&lt; "[9] B2::cb2 = " &lt;&lt; (char)pVtab[9] &lt;&lt; endl;</p>
<p>cout &lt;&lt; "[10] D::id = " &lt;&lt; (int)pVtab[10] &lt;&lt; endl;</p>
<p>cout &lt;&lt; "[11] D::cd = " &lt;&lt; (char)pVtab[11] &lt;&lt; endl;</p>
<p>程序运行结果如下：</p>
<span>
<table id=table1 border=1 cellSpacing=0 cellPadding=0>
    <tbody>
        <tr>
            <td width=278>
            <p align=center><strong><font color=#000000 size=3 face="Times New Roman">GCC 3.4.4</font></strong></p>
            </td>
            <td width=269>
            <p align=center><strong><font color=#000000 size=3 face="Times New Roman">VC++ 2003</font></strong></p>
            </td>
        </tr>
        <tr>
            <td vAlign=top width=278>
            <p><span><font size=2><strong><font face="Courier New">[0] D::B1::_vptr-&gt;</font></strong></font></span></p>
            <p><span><font size=2><strong><font face="Courier New">&nbsp;&nbsp;&nbsp;&nbsp; [0] D::f()</font></strong></font></span></p>
            <p><span><font size=2><strong><font face="Courier New">&nbsp;&nbsp;&nbsp;&nbsp; [1] B::Bf()</font></strong></font></span></p>
            <p><span><font size=2><strong><font face="Courier New">&nbsp;&nbsp;&nbsp;&nbsp; [2] D::f1()</font></strong></font></span></p>
            <p><span><font size=2><strong><font face="Courier New">&nbsp;&nbsp;&nbsp;&nbsp; [3] B1::Bf1()</font></strong></font></span></p>
            <p><span><font size=2><strong><font face="Courier New">&nbsp;&nbsp;&nbsp;&nbsp; [4] D::f2()</font></strong></font></span></p>
            <p><span><font size=2><strong><font face="Courier New">&nbsp;&nbsp;&nbsp;&nbsp; [5] 0x1</font></strong></font></span></p>
            <p><span><font size=2><strong><font face="Courier New">[1] B::ib = 0</font></strong></font></span></p>
            <p><span><font size=2><strong><font face="Courier New">[2] B::cb = B</font></strong></font></span></p>
            <p><span><font size=2><strong><font face="Courier New">[3] B1::ib1 = 11</font></strong></font></span></p>
            <p><span><font size=2><strong><font face="Courier New">[4] B1::cb1 = 1</font></strong></font></span></p>
            <p><span><font size=2><strong><font face="Courier New">[5] D::B2::_vptr-&gt;</font></strong></font></span></p>
            <p><span><font size=2><strong><font face="Courier New">&nbsp;&nbsp;&nbsp;&nbsp; [0] D::f()</font></strong></font></span></p>
            <p><span><font size=2><strong><font face="Courier New">&nbsp;&nbsp;&nbsp;&nbsp; [1] B::Bf()</font></strong></font></span></p>
            <p><span><font size=2><strong><font face="Courier New">&nbsp;&nbsp;&nbsp; &nbsp;[2] D::f2()</font></strong></font></span></p>
            <p><span><font size=2><strong><font face="Courier New">&nbsp;&nbsp;&nbsp;&nbsp; [3] B2::Bf2()</font></strong></font></span></p>
            <p><span><font size=2><strong><font face="Courier New">&nbsp;&nbsp;&nbsp;&nbsp; [4] 0x0</font></strong></font></span></p>
            <p><span><font size=2><strong><font face="Courier New">[6] B::ib = 0</font></strong></font></span></p>
            <p><span><font size=2><strong><font face="Courier New">[7] B::cb = B</font></strong></font></span></p>
            <p><span><font size=2><strong><font face="Courier New">[8] B2::ib2 = 12</font></strong></font></span></p>
            <p><span><font size=2><strong><font face="Courier New">[9] B2::cb2 = 2</font></strong></font></span></p>
            <p><font color=#c0c0c0 size=2><strong><font face="Courier New">[10] D::id = 100</font></strong></font></p>
            <p><font color=#c0c0c0 size=2><strong><font face="Courier New">[11] D::cd = D</font></strong></font></p>
            </td>
            <td vAlign=top width=269>
            <p><span><font size=2><strong><font face="Courier New">[0] D::B1::_vptr-&gt;</font></strong></font></span></p>
            <p><span><font size=2><strong><font face="Courier New">&nbsp;&nbsp;&nbsp;&nbsp; [0] D::f()</font></strong></font></span></p>
            <p><span><font size=2><strong><font face="Courier New">&nbsp;&nbsp;&nbsp;&nbsp; [1] B::Bf()</font></strong></font></span></p>
            <p><span><font size=2><strong><font face="Courier New">&nbsp;&nbsp;&nbsp;&nbsp; [2] D::f1()</font></strong></font></span></p>
            <p><span><font size=2><strong><font face="Courier New">&nbsp;&nbsp;&nbsp;&nbsp; [3] B1::Bf1()</font></strong></font></span></p>
            <p><span><font size=2><strong><font face="Courier New">&nbsp;&nbsp;&nbsp;&nbsp; [4] D::Df()</font></strong></font></span></p>
            <p><span><font size=2><strong><font face="Courier New">&nbsp;&nbsp;&nbsp;&nbsp; [5] 0x00000000</font></strong></font></span></p>
            <p><span><font size=2><strong><font face="Courier New">[1] B::ib = 0</font></strong></font></span></p>
            <p><span><font size=2><strong><font face="Courier New">[2] B::cb = B</font></strong></font></span></p>
            <p><span><font size=2><strong><font face="Courier New">[3] B1::ib1 = 11</font></strong></font></span></p>
            <p><span><font size=2><strong><font face="Courier New">[4] B1::cb1 = 1</font></strong></font></span></p>
            <p><span><font size=2><strong><font face="Courier New">[5] D::B2::_vptr-&gt;</font></strong></font></span></p>
            <p><span><font size=2><strong><font face="Courier New">&nbsp;&nbsp;&nbsp;&nbsp; [0] D::f()</font></strong></font></span></p>
            <p><span><font size=2><strong><font face="Courier New">&nbsp;&nbsp;&nbsp;&nbsp; [1] B::Bf()</font></strong></font></span></p>
            <p><span><font size=2><strong><font face="Courier New">&nbsp;&nbsp;&nbsp;&nbsp; [2] D::f2()</font></strong></font></span></p>
            <p><span><font size=2><strong><font face="Courier New">&nbsp;&nbsp;&nbsp;&nbsp; [3] B2::Bf2()</font></strong></font></span></p>
            <p><span><font size=2><strong><font face="Courier New">&nbsp;&nbsp;&nbsp;&nbsp; [4] 0x00000000</font></strong></font></span></p>
            <p><span><font size=2><strong><font face="Courier New">[6] B::ib = 0</font></strong></font></span></p>
            <p><span><font size=2><strong><font face="Courier New">[7] B::cb = B</font></strong></font></span></p>
            <p><span><font size=2><strong><font face="Courier New">[8] B2::ib2 = 12</font></strong></font></span></p>
            <p><span><font size=2><strong><font face="Courier New">[9] B2::cb2 = 2</font></strong></font></span></p>
            <p><font color=#c0c0c0 size=2><strong><font face="Courier New">[10] D::id = 100</font></strong></font></p>
            <p><strong><font color=#c0c0c0 size=2 face="Courier New">[11] D::cd = D</font></strong></p>
            </td>
        </tr>
    </tbody>
</table>
</span>
<p>下面是对于子类实例中的虚函数表的图：</p>
<p><img src="http://www.uml.org.cn/c++/images/dd06.jpg" width=400 height=305></p>
<p>我们可以看见，最顶端的父类B其成员变量存在于B1和B2中，并被D给继承下去了。而在D中，其有B1和B2的实例，于是B的成员在D的实例中存在两份，一份是B1继承而来的，另一份是B2继承而来的。所以，如果我们使用以下语句，则会产生二义性编译错误：</p>
<p>D d;</p>
<p>d.ib = 0; //二义性错误</p>
<p>d.B1::ib = 1; //正确</p>
<p>d.B2::ib = 2; //正确</p>
<p>注意，上面例程中的最后两条语句存取的是两个变量。虽然我们消除了二义性的编译错误，但B类在D中还是有两个实例，这种继承造成了数据的重复，我们叫这种继承为重复继承。重复的基类数据成员可能并不是我们想要的。所以，C++引入了虚基类的概念。</p>
<p><strong>钻石型多重虚拟继承</strong> </p>
<p>虚拟继承的出现就是为了解决重复继承中多个间接父类的问题的。钻石型的结构是其最经典的结构。也是我们在这里要讨论的结构：</p>
<p>上述的&#8220;重复继承&#8221;只需要把B1和B2继承B的语法中加上virtual 关键，就成了虚拟继承，其继承图如下所示：</p>
<p><img src="http://www.uml.org.cn/c++/images/dd07.jpg" width=253 height=404></p>
<p>上图和前面的&#8220;重复继承&#8221;中的类的内部数据和接口都是完全一样的，只是我们采用了虚拟继承：其省略后的源码如下所示：</p>
<p>class B {&#8230;&#8230;};</p>
<p>class B1 : virtual public B{&#8230;&#8230;};</p>
<p>class B2: virtual public B{&#8230;&#8230;};</p>
<p>class D : public B1, public B2{ &#8230;&#8230; };</p>
<p>在查看D之前，我们先看一看单一虚拟继承的情况。下面是一段在VC++2003下的测试程序：（因为VC++和GCC的内存而局上有一些细节上的不同，所以这里只给出VC++的程序，GCC下的程序大家可以根据我给出的程序自己仿照着写一个去试一试）：</p>
<p>int** pVtab = NULL;</p>
<p>Fun pFun = NULL;</p>
<p>&nbsp;</p>
<p>B1 bb1;</p>
<p>pVtab = (int**)&amp;bb1;</p>
<p>cout &lt;&lt; "[0] B1::_vptr-&gt;" &lt;&lt; endl;</p>
<p>pFun = (Fun)pVtab[0][0];</p>
<p>cout &lt;&lt; " [0] ";</p>
<p>pFun(); //B1::f1();</p>
<p>cout &lt;&lt; " [1] ";</p>
<p>pFun = (Fun)pVtab[0][1];</p>
<p>pFun(); //B1::bf1();</p>
<p>cout &lt;&lt; " [2] ";</p>
<p>cout &lt;&lt; pVtab[0][2] &lt;&lt; endl;</p>
<p>cout &lt;&lt; "[1] = 0x";</p>
<p>cout &lt;&lt; (int*)*((int*)(&amp;bb1)+1) &lt;&lt;endl; //B1::ib1</p>
<p>cout &lt;&lt; "[2] B1::ib1 = ";</p>
<p>cout &lt;&lt; (int)*((int*)(&amp;bb1)+2) &lt;&lt;endl; //B1::ib1</p>
<p>cout &lt;&lt; "[3] B1::cb1 = ";</p>
<p>cout &lt;&lt; (char)*((int*)(&amp;bb1)+3) &lt;&lt; endl; //B1::cb1</p>
<p>cout &lt;&lt; "[4] = 0x";</p>
<p>cout &lt;&lt; (int*)*((int*)(&amp;bb1)+4) &lt;&lt; endl; //NULL</p>
<p>cout &lt;&lt; "[5] B::_vptr-&gt;" &lt;&lt; endl;</p>
<p>pFun = (Fun)pVtab[5][0];</p>
<p>cout &lt;&lt; " [0] ";</p>
<p>pFun(); //B1::f();</p>
<p>pFun = (Fun)pVtab[5][1];</p>
<p>cout &lt;&lt; " [1] ";</p>
<p>pFun(); //B::Bf();</p>
<p>cout &lt;&lt; " [2] ";</p>
<p>cout &lt;&lt; "0x" &lt;&lt; (Fun)pVtab[5][2] &lt;&lt; endl;</p>
<p>cout &lt;&lt; "[6] B::ib = ";</p>
<p>cout &lt;&lt; (int)*((int*)(&amp;bb1)+6) &lt;&lt;endl; //B::ib</p>
<p>cout &lt;&lt; "[7] B::cb = ";</p>
<p>其运行结果如下（我结出了GCC的和VC++2003的对比）：</p>
<table id=table1 border=1 cellSpacing=0 cellPadding=0>
    <tbody>
        <tr>
            <td width=295>
            <p align=center><span><strong><font color=#000000 size=3>GCC 3.4.4</font></strong></span></p>
            </td>
            <td width=295>
            <p align=center><span><strong><font color=#000000 size=3>VC++ 2003</font></strong></span></p>
            </td>
        </tr>
        <tr>
            <td vAlign=top width=295>
            <p><span><strong><span>[0] B1::_vptr -&gt;</span></strong></span></p>
            <p><span><strong><span>&nbsp;&nbsp;&nbsp; [0] : B1::f()</span></strong></span></p>
            <p><span><strong><span>&nbsp;&nbsp;&nbsp; [1] : B1::f1()</span></strong></span></p>
            <p><span><strong><span>&nbsp;&nbsp;&nbsp; [2] : B1::Bf1()</span></strong></span></p>
            <p><span><strong><span>&nbsp;&nbsp;&nbsp; [3] : 0</span></strong></span></p>
            <p><span><strong><span>[1] B1::ib1 : 11</span></strong></span></p>
            <p><span><strong><span>[2] B1::cb1 : 1</span></strong></span></p>
            <p><span><strong><span>[3] B::_vptr -&gt;</span></strong></span></p>
            <p><span><strong><span>&nbsp;&nbsp;&nbsp; [0] : B1::f()</span></strong></span></p>
            <p><span><strong><span>&nbsp;&nbsp;&nbsp; [1] : B::Bf()</span></strong></span></p>
            <p><span><strong><span>&nbsp;&nbsp;&nbsp; [2] : 0</span></strong></span></p>
            <p><span><strong><span>[4] B::ib : 0</span></strong></span></p>
            <p><span><strong><span>[5] B::cb : B</span></strong></span></p>
            <p><span><strong><span>[6] NULL : 0</span></strong></span></p>
            </td>
            <td vAlign=top width=295>
            <p><span><strong><span>[0] B1::_vptr-&gt;</span></strong></span></p>
            <p><span><strong><span>&nbsp;&nbsp;&nbsp;&nbsp; [0] B1::f1()</span></strong></span></p>
            <p><span><strong><span>&nbsp;&nbsp;&nbsp;&nbsp; [1] B1::Bf1()</span></strong></span></p>
            <p><span><strong><span>&nbsp;&nbsp;&nbsp;&nbsp; [2] 0</span></strong></span></p>
            <p><span><strong><span>[1] = 0x00454310</span><span> </span><span>&#231;</span><span>该地址取值后是</span><span>-4</span></strong></span></p>
            <p><span><strong><span>[2] B1::ib1 = 11</span></strong></span></p>
            <p><span><strong><span>[3] B1::cb1 = 1</span></strong></span></p>
            <p><span><strong><span>[4] = 0x00000000</span></strong></span></p>
            <p><span><strong><span>[5] B::_vptr-&gt;</span></strong></span></p>
            <p><span><strong><span>&nbsp;&nbsp;&nbsp;&nbsp; [0] B1::f()</span></strong></span></p>
            <p><span><strong><span>&nbsp;&nbsp;&nbsp;&nbsp; [1] B::Bf()</span></strong></span></p>
            <p><span><strong><span>&nbsp;&nbsp;&nbsp;&nbsp; [2] 0x00000000</span></strong></span></p>
            <p><span><strong><span>[6] B::ib = 0</span></strong></span></p>
            <p><span><strong><span>[7] B::cb = B</span></strong></span></p>
            </td>
        </tr>
    </tbody>
</table>
<p>这里，大家可以自己对比一下。关于细节上，我会在后面一并再说。</p>
<p>下面的测试程序是看子类D的内存布局，同样是VC++ 2003的（因为VC++和GCC的内存布局上有一些细节上的不同，而VC++的相对要清楚很多，所以这里只给出VC++的程序，GCC下的程序大家可以根据我给出的程序自己仿照着写一个去试一试）：</p>
<p>D d;</p>
<p>pVtab = (int**)&amp;d;</p>
<p>cout &lt;&lt; "[0] D::B1::_vptr-&gt;" &lt;&lt; endl;</p>
<p>pFun = (Fun)pVtab[0][0];</p>
<p>cout &lt;&lt; " [0] "; pFun(); //D::f1();</p>
<p>pFun = (Fun)pVtab[0][1];</p>
<p>cout &lt;&lt; " [1] "; pFun(); //B1::Bf1();</p>
<p>pFun = (Fun)pVtab[0][2];</p>
<p>cout &lt;&lt; " [2] "; pFun(); //D::Df();</p>
<p>pFun = (Fun)pVtab[0][3];</p>
<p>cout &lt;&lt; " [3] ";</p>
<p>cout &lt;&lt; pFun &lt;&lt; endl;</p>
<p>//cout &lt;&lt; pVtab[4][2] &lt;&lt; endl;</p>
<p>cout &lt;&lt; "[1] = 0x";</p>
<p>cout &lt;&lt; (int*)((&amp;dd)+1) &lt;&lt;endl; //????</p>
<p>cout &lt;&lt; "[2] B1::ib1 = ";</p>
<p>cout &lt;&lt; *((int*)(&amp;dd)+2) &lt;&lt;endl; //B1::ib1</p>
<p>cout &lt;&lt; "[3] B1::cb1 = ";</p>
<p>cout &lt;&lt; (char)*((int*)(&amp;dd)+3) &lt;&lt; endl; //B1::cb1</p>
<p>//---------------------</p>
<p>cout &lt;&lt; "[4] D::B2::_vptr-&gt;" &lt;&lt; endl;</p>
<p>pFun = (Fun)pVtab[4][0];</p>
<p>cout &lt;&lt; " [0] "; pFun(); //D::f2();</p>
<p>pFun = (Fun)pVtab[4][1];</p>
<p>cout &lt;&lt; " [1] "; pFun(); //B2::Bf2();</p>
<p>pFun = (Fun)pVtab[4][2];</p>
<p>cout &lt;&lt; " [2] ";</p>
<p>cout &lt;&lt; pFun &lt;&lt; endl;</p>
<p>cout &lt;&lt; "[5] = 0x";</p>
<p>cout &lt;&lt; *((int*)(&amp;dd)+5) &lt;&lt; endl; // ???</p>
<p>cout &lt;&lt; "[6] B2::ib2 = ";</p>
<p>cout &lt;&lt; (int)*((int*)(&amp;dd)+6) &lt;&lt;endl; //B2::ib2</p>
<p>cout &lt;&lt; "[7] B2::cb2 = ";</p>
<p>cout &lt;&lt; (char)*((int*)(&amp;dd)+7) &lt;&lt; endl; //B2::cb2</p>
<p>cout &lt;&lt; "[8] D::id = ";</p>
<p>cout &lt;&lt; *((int*)(&amp;dd)+8) &lt;&lt; endl; //D::id</p>
<p>cout &lt;&lt; "[9] D::cd = ";</p>
<p>cout &lt;&lt; (char)*((int*)(&amp;dd)+9) &lt;&lt; endl;//D::cd</p>
<p>cout &lt;&lt; "[10] = 0x";</p>
<p>cout &lt;&lt; (int*)*((int*)(&amp;dd)+10) &lt;&lt; endl;</p>
<p>//---------------------</p>
<p>cout &lt;&lt; "[11] D::B::_vptr-&gt;" &lt;&lt; endl;</p>
<p>pFun = (Fun)pVtab[11][0];</p>
<p>cout &lt;&lt; " [0] "; pFun(); //D::f();</p>
<p>pFun = (Fun)pVtab[11][1];</p>
<p>cout &lt;&lt; " [1] "; pFun(); //B::Bf();</p>
<p>pFun = (Fun)pVtab[11][2];</p>
<p>cout &lt;&lt; " [2] ";</p>
<p>cout &lt;&lt; pFun &lt;&lt; endl;</p>
<p>cout &lt;&lt; "[12] B::ib = ";</p>
<p>cout &lt;&lt; *((int*)(&amp;dd)+12) &lt;&lt; endl; //B::ib</p>
<p>cout &lt;&lt; "[13] B::cb = ";</p>
<p>cout &lt;&lt; (char)*((int*)(&amp;dd)+13) &lt;&lt;endl;//B::cb</p>
<p>下面给出运行后的结果（分VC++和GCC两部份）</p>
<table id=table1 border=1 cellSpacing=0 cellPadding=0>
    <tbody>
        <tr>
            <td width=271>
            <p align=center><strong><font color=#000000 size=3>GCC 3.4.4</font></strong></p>
            </td>
            <td width=319>
            <p align=center><strong><font color=#000000 size=3>VC++ 2003</font></strong></p>
            </td>
        </tr>
        <tr>
            <td vAlign=top width=271>
            <p><strong><span>[0] B1::_vptr -&gt;</span></strong></p>
            <p><strong><span>&nbsp;&nbsp;&nbsp; [0] : D::f()</span></strong></p>
            <p><strong><span>&nbsp;&nbsp;&nbsp; [1] : D::f1()</span></strong></p>
            <p><strong><span>&nbsp;&nbsp;&nbsp; [2] : B1::Bf1()</span></strong></p>
            <p><strong><span>&nbsp;&nbsp;&nbsp; [3] : D::f2()</span></strong></p>
            <p><strong><span>&nbsp;&nbsp;&nbsp; [4] : D::Df()</span></strong></p>
            <p><strong><span>&nbsp;&nbsp;&nbsp; [5] : 1</span></strong></p>
            <p><strong><span>[1] B1::ib1 : 11</span></strong></p>
            <p><strong><span>[2] B1::cb1 : 1</span></strong></p>
            <p><strong><span>[3] B2::_vptr -&gt;</span></strong></p>
            <p><strong><span>&nbsp;&nbsp;&nbsp; [0] : D::f()</span></strong></p>
            <p><strong><span>&nbsp;&nbsp;&nbsp; [1] : D::f2()</span></strong></p>
            <p><strong><span>&nbsp;&nbsp;&nbsp; [2] : B2::Bf2()</span></strong></p>
            <p><strong><span>&nbsp;&nbsp;&nbsp; [3] : 0</span></strong></p>
            <p><strong><span>[4] B2::ib2 : 12</span></strong></p>
            <p><strong><span>[5] B2::cb2 : 2</span></strong></p>
            <p><strong><span>[6] D::id : 100</span></strong></p>
            <p><strong><span>[7] D::cd : D</span></strong></p>
            <p><strong><span>[8] B::_vptr -&gt;</span></strong></p>
            <p><strong><span>&nbsp;&nbsp;&nbsp; [0] : D::f()</span></strong></p>
            <p><strong><span>&nbsp;&nbsp;&nbsp; [1] : B::Bf()</span></strong></p>
            <p><strong><span>&nbsp;&nbsp;&nbsp; [2] : 0</span></strong></p>
            <p><strong><span>[9] B::ib : 0</span></strong></p>
            <p><strong><span>[10] B::cb : B</span></strong></p>
            <p><strong><span>[11] NULL : 0</span></strong></p>
            </td>
            <td vAlign=top width=319>
            <p><strong><span>[0] D::B1::_vptr-&gt;</span></strong></p>
            <p><strong><span>&nbsp;&nbsp;&nbsp;&nbsp; [0] D::f1()</span></strong></p>
            <p><strong><span>&nbsp;&nbsp;&nbsp;&nbsp; [1] B1::Bf1()</span></strong></p>
            <p><strong><span>&nbsp;&nbsp;&nbsp;&nbsp; [2] D::Df()</span></strong></p>
            <p><strong><span>&nbsp;&nbsp;&nbsp;&nbsp; [3] 00000000</span></strong></p>
            <p><strong><span>[1] = 0x0013FDC4&nbsp; </span><span>&#231;</span><span> </span><span>该地址取值后是</span><span>-4</span></strong></p>
            <p><strong><span>[2] B1::ib1 = 11</span></strong></p>
            <p><strong><span>[3] B1::cb1 = 1</span></strong></p>
            <p><strong><span>[4] D::B2::_vptr-&gt;</span></strong></p>
            <p><strong><span>&nbsp;&nbsp;&nbsp;&nbsp; [0] D::f2()</span></strong></p>
            <p><strong><span>&nbsp;&nbsp;&nbsp;&nbsp; [1] B2::Bf2()</span></strong></p>
            <p><strong><span>&nbsp;&nbsp;&nbsp;&nbsp; [2] 00000000</span></strong></p>
            <p><strong><span>[5] = 0x4539260&nbsp;&nbsp; </span><span>&#231;</span><span> </span><span>该地址取值后是</span><span>-4</span></strong></p>
            <p><strong><span>[6] B2::ib2 = 12</span></strong></p>
            <p><strong><span>[7] B2::cb2 = 2</span></strong></p>
            <p><strong><span>[8] D::id = 100</span></strong></p>
            <p><strong><span>[9] D::cd = D</span></strong></p>
            <p><strong><span>[10]&nbsp; = 0x00000000</span></strong></p>
            <p><strong><span>[11] D::B::_vptr-&gt;</span></strong></p>
            <p><strong><span>&nbsp;&nbsp;&nbsp;&nbsp; [0] D::f()</span></strong></p>
            <p><strong><span>&nbsp;&nbsp;&nbsp;&nbsp; [1] B::Bf()</span></strong></p>
            <p><strong><span>&nbsp;&nbsp;&nbsp;&nbsp; [2] 00000000</span></strong></p>
            <p><strong><span>[12] B::ib = 0</span></strong></p>
            <p><strong><span>[13] B::cb = B</span></strong></p>
            </td>
        </tr>
    </tbody>
</table>
<p>关于虚拟继承的运行结果我就不画图了（前面的作图已经让我产生了很严重的厌倦感，所以就偷个懒了，大家见谅了）</p>
<p>在上面的输出结果中，我用不同的颜色做了一些标明。我们可以看到如下的几点：</p>
<p>1）无论是GCC还是VC++，除了一些细节上的不同，其大体上的对象布局是一样的。也就是说，先是B1（黄色），然后是B2（绿色），接着是D（灰色），而B这个超类（青蓝色）的实例都放在最后的位置。</p>
<p>2）关于虚函数表，尤其是第一个虚表，GCC和VC++有很重大的不一样。但仔细看下来，还是VC++的虚表比较清晰和有逻辑性。</p>
<p>3）VC++和GCC都把B这个超类放到了最后，而VC++有一个NULL分隔符把B和B1和B2的布局分开。GCC则没有。</p>
<p>4）VC++中的内存布局有两个地址我有些不是很明白，在其中我用红色标出了。取其内容是-4。接道理来说，这个指针应该是指向B类实例的内存地址（这个做法就是为了保证重复的父类只有一个实例的技术）。但取值后却不是。这点我目前还并不太清楚，还向大家请教。</p>
<p>5）GCC的内存布局中在B1和B2中则没有指向B的指针。这点可以理解，编译器可以通过计算B1和B2的size而得出B的偏移量。</p>
<p><strong>结束语</strong></p>
<p>C++这门语言是一门比较复杂的语言，对于程序员来说，我们似乎永远摸不清楚这门语言背着我们在干了什么。需要熟悉这门语言，我们就必需要了解C++里面的那些东西，需要我们去了解他后面的内存对象。这样我们才能真正的了解C++，从而能够更好的使用C++这门最难的编程语言。</p>
<p>在文章束之前还是介绍一下自己吧。我从事软件研发有十个年头了，目前是软件开发技术主管，技术方面，主攻Unix/C/C++，比较喜欢网络上的技术，比如分布式计算，网格计算，P2P，Ajax等一切和互联网相关的东西。管理方面比较擅长于团队建设，技术趋势分析，项目管理。欢迎大家和我交流，我的MSN和Email是：haoel@hotmail.com </p>
</div>
<img src ="http://www.cppblog.com/tianbianlan/aggbug/113987.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/tianbianlan/" target="_blank">天边蓝</a> 2010-04-29 19:30 <a href="http://www.cppblog.com/tianbianlan/archive/2010/04/29/113987.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Boost.Regex库学习笔记</title><link>http://www.cppblog.com/tianbianlan/archive/2009/07/24/91015.html</link><dc:creator>天边蓝</dc:creator><author>天边蓝</author><pubDate>Fri, 24 Jul 2009 03:48:00 GMT</pubDate><guid>http://www.cppblog.com/tianbianlan/archive/2009/07/24/91015.html</guid><wfw:comment>http://www.cppblog.com/tianbianlan/comments/91015.html</wfw:comment><comments>http://www.cppblog.com/tianbianlan/archive/2009/07/24/91015.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/tianbianlan/comments/commentRss/91015.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/tianbianlan/services/trackbacks/91015.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: &nbsp;在C++编程中，有一点让人挺遗憾的就是C++尚不支持正则表达式，这让很多用户为了编写支持正则表达式程序而不得不放弃C++。然而，Boost.Regex库填补了C++在这方面的空白，它使C++很好的支持各种引擎的正则表达式。&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 结合我的学习，逐步分析Boost.Regex库。&nbsp;&nbsp;&nbs...&nbsp;&nbsp;<a href='http://www.cppblog.com/tianbianlan/archive/2009/07/24/91015.html'>阅读全文</a><img src ="http://www.cppblog.com/tianbianlan/aggbug/91015.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/tianbianlan/" target="_blank">天边蓝</a> 2009-07-24 11:48 <a href="http://www.cppblog.com/tianbianlan/archive/2009/07/24/91015.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>