﻿<?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++博客-lemene</title><link>http://www.cppblog.com/lemene/</link><description /><language>zh-cn</language><lastBuildDate>Tue, 07 Apr 2026 22:55:06 GMT</lastBuildDate><pubDate>Tue, 07 Apr 2026 22:55:06 GMT</pubDate><ttl>60</ttl><item><title /><link>http://www.cppblog.com/lemene/archive/2017/12/21/215437.html</link><dc:creator>lemene</dc:creator><author>lemene</author><pubDate>Thu, 21 Dec 2017 08:59:00 GMT</pubDate><guid>http://www.cppblog.com/lemene/archive/2017/12/21/215437.html</guid><wfw:comment>http://www.cppblog.com/lemene/comments/215437.html</wfw:comment><comments>http://www.cppblog.com/lemene/archive/2017/12/21/215437.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/lemene/comments/commentRss/215437.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/lemene/services/trackbacks/215437.html</trackback:ping><description><![CDATA[<span/><img src ="http://www.cppblog.com/lemene/aggbug/215437.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/lemene/" target="_blank">lemene</a> 2017-12-21 16:59 <a href="http://www.cppblog.com/lemene/archive/2017/12/21/215437.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>K近邻算法</title><link>http://www.cppblog.com/lemene/archive/2016/10/28/214366.html</link><dc:creator>lemene</dc:creator><author>lemene</author><pubDate>Fri, 28 Oct 2016 08:18:00 GMT</pubDate><guid>http://www.cppblog.com/lemene/archive/2016/10/28/214366.html</guid><wfw:comment>http://www.cppblog.com/lemene/comments/214366.html</wfw:comment><comments>http://www.cppblog.com/lemene/archive/2016/10/28/214366.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/lemene/comments/commentRss/214366.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/lemene/services/trackbacks/214366.html</trackback:ping><description><![CDATA[<h1>概述
</h1><p><span style="font-family:宋体; font-size:12pt">k近邻（k nearest neighbor）算法是一种监督算法，用于分类。它基本思想是计算新实例和训练集元素的**距离**，找出k个最接近的实例（neighbor），统计它们所属分类，次数最多的类别作为新实例的类别。
</span></p><h1>原理与步骤
</h1><p><span style="font-family:宋体; font-size:12pt">监督算法可大致分成两个步骤：训练（train）和分类（classify）。从实现考虑还需要算法初始化过程。
</span></p><p><span style="font-family:宋体; font-size:12pt">本节的代码为python风格的示意代码，不能直接运行，可运行代码参考zxml。
</span></p><p><span style="font-family:宋体; font-size:12pt"><strong>示意代码</strong>
		</span></p><p style="background: #eeeeee; margin-left: 24pt">
 </p><p style="background: #eeeeee; margin-left: 24pt"><pre><code>class KNearestNeighbor:
</code></pre></p><p style="background: #eeeeee; margin-left: 24pt"><pre><code>    def __init__(...):  pass
</code></pre></p><p style="background: #eeeeee; margin-left: 24pt"><pre><code>    def train(...):     pass
</code></pre></p><p style="background: #eeeeee; margin-left: 24pt"><pre><code>    def classify(...):  pass
</code></pre></p><h2>训练（train）
</h2><p><span style="font-family:宋体; font-size:12pt">理论上k近邻算法不需要训练，可直接使用原始数据进行分类。
</span></p><p><span style="font-family:宋体; font-size:12pt"><strong>归一化</strong>
		</span></p><p><span style="font-family:宋体; font-size:12pt">数据的分类的量纲差别较大时，小量纲分类在计算的权重将被削弱。使用归一化消除这种影响。方法如下：
</span></p><p style="text-align: center"><span style="font-family:Times New Roman"><em>x̂</em> = (<em>x</em> − <em>x<sub>min</sub></em>)/(<em>x<sub>max</sub></em> − <em>x<sub>min</sub></em>) 
</span></p><p><span style="font-family:宋体; font-size:12pt"><strong>预处理</strong>
		</span></p><p><span style="font-family:宋体; font-size:12pt">将数据进行某种形式的处理可加快寻找k近邻的速度，常用的处理方式有KD-Tree和Ball-Tree，前者对低维欧氏距离有效，后者对所有距离有效。
</span></p><p><span style="font-family:宋体; font-size:12pt"><strong>示意代码</strong>
		</span></p><p style="background: #eeeeee; margin-left: 24pt">
 </p><p style="background: #eeeeee; margin-left: 24pt"><pre><code>def train(self, X, C):
</code></pre></p><p style="background: #eeeeee; margin-left: 24pt"><pre><code>    '''X,C分别代表实例和类别'''
</code></pre></p><p style="background: #eeeeee; margin-left: 24pt">
 </p><p style="background: #eeeeee; margin-left: 24pt"><pre><code>    # 实例数据归一化，并保留数据备份
</code></pre></p><p style="background: #eeeeee; margin-left: 24pt"><pre><code>    (self.X, self.C) = (normalize(X), C.copy())
</code></pre></p><p style="background: #eeeeee; margin-left: 24pt">
 </p><p style="background: #eeeeee; margin-left: 24pt"><pre><code>    # 可选，如果需要，则构建KD-Tree()
</code></pre></p><p style="background: #eeeeee; margin-left: 24pt"><pre><code>    self.tree = KDTree()
</code></pre></p><p style="background: #eeeeee; margin-left: 24pt"><pre><code>    self.tree.create(self.X)
</code></pre></p><h2>分类（classify）
</h2><p><span style="font-family:宋体; font-size:12pt">分类的大致步骤：<em>找出k个近邻</em> 和*统计类别的次数* 。 分类的部分处理与训练的处理向对应，如：
</span></p><ul><li>训练对数据进行归一化，则分类是也需要归一化。
</li><li>训练使用如KD-Tree等方式进行处理，则分类使用对应的方法寻找k个近邻。
</li></ul><p><span style="font-family:宋体; font-size:12pt"><strong>示意代码</strong>
		</span></p><p style="background: #eeeeee; margin-left: 24pt">
 </p><p style="background: #eeeeee; margin-left: 24pt"><pre><code>def classify(self, x):
</code></pre></p><p style="background: #eeeeee; margin-left: 24pt">
 </p><p style="background: #eeeeee; margin-left: 24pt"><pre><code>    _x = normalize(x)                   # 将x归一化
</code></pre></p><p style="background: #eeeeee; margin-left: 24pt"><pre><code>    nearest = self.find_neighbors(_x)   # 找出k个近邻
</code></pre></p><p style="background: #eeeeee; margin-left: 24pt"><pre><code>    freq = frequency(nearests)          # 统计每个类型的次数
</code></pre></p><p style="background: #eeeeee; margin-left: 24pt"><pre><code>    return freq.sorted()[-1]            # 排序后，返回次数最多的类别
</code></pre></p><p style="background: #eeeeee; margin-left: 24pt">
 </p><p style="background: #eeeeee; margin-left: 24pt"><pre><code>def find_neighbors(self, x):
</code></pre></p><p style="background: #eeeeee; margin-left: 24pt"><pre><code>    '''寻找与x最接近的k个点'''
</code></pre></p><p style="background: #eeeeee; margin-left: 24pt">
 </p><p style="background: #eeeeee; margin-left: 24pt"><pre><code>    if self.tree == None:               # 判断是否使用了kd-tree
</code></pre></p><p style="background: #eeeeee; margin-left: 24pt"><pre><code>        ds = self.distance(x, self.X)   # 计算所有点的距离
</code></pre></p><p style="background: #eeeeee; margin-left: 24pt"><pre><code>        indices = ds.argsort()[0:k]     # 排序后，取前面k个
</code></pre></p><p style="background: #eeeeee; margin-left: 24pt">
 </p><p style="background: #eeeeee; margin-left: 24pt"><pre><code>    else:
</code></pre></p><p style="background: #eeeeee; margin-left: 24pt"><pre><code>        indices = self.tree.find_neighbors(x, self.k)
</code></pre></p><p style="background: #eeeeee; margin-left: 24pt">
 </p><p style="background: #eeeeee; margin-left: 24pt"><pre><code>    # indices是k个近邻的索引位置
</code></pre></p><p style="background: #eeeeee; margin-left: 24pt"><pre><code>    return self.C[indices]
</code></pre></p><h2>初始化（init）
</h2><p><span style="font-family:宋体; font-size:12pt">初始化需要设置算法参数，如k的值，距离公式。
</span></p><p><span style="font-family:宋体; font-size:12pt"><strong>距离</strong>
		</span></p><p><span style="font-family:宋体; font-size:12pt">实例之间的距离一般采用欧氏距离，但不排除使用其它的距离计算方法。欧氏距离：
</span></p><p style="text-align: center"><span style="font-family:Times New Roman"><em>d</em> = </span><span style="font-family:宋体">∥</span><span style="font-family:Times New Roman"><em>x</em> − <em>y</em></span><span style="font-family:宋体">∥</span><span style="font-family:Times New Roman"> = <span style="font-size:18pt">√</span>(<span style="font-size:15pt">∑</span>(<em>x<sub>i</sub></em> − <em>y<sub>i</sub></em>)<sup>2</sup>) ≥ </span><span style="font-family:宋体">∥</span><span style="font-family:Times New Roman"><em>x<sub>i</sub></em> − <em>y<sub>i</sub></em></span><span style="font-family:宋体">∥</span><span style="font-family:Times New Roman">
		</span></p><p style="background: #eeeeee; margin-left: 24pt">
 </p><p style="background: #eeeeee; margin-left: 24pt"><pre><code>def __init__(self, k, distance=euclidean ):
</code></pre></p><p style="background: #eeeeee; margin-left: 24pt"><pre><code>    (self.k, self.distance) = (k, distance)
</code></pre></p><h1>scikit-learn
</h1><p><span style="font-family:宋体; font-size:12pt">下面使用scikit-learn中的k近邻算法分类的例子。
</span></p><p style="background: #eeeeee; margin-left: 24pt">
 </p><p style="background: #eeeeee; margin-left: 24pt"><pre><code>import numpy as np
</code></pre></p><p style="background: #eeeeee; margin-left: 24pt"><pre><code>from sklearn import neighbors
</code></pre></p><p style="background: #eeeeee; margin-left: 24pt">
 </p><p style="background: #eeeeee; margin-left: 24pt"><pre><code># 准备数据，分成A B两类。A类在[0,0]附近，B类在[1,1]附近。
</code></pre></p><p style="background: #eeeeee; margin-left: 24pt"><pre><code>X = np.array([[0, 0.1],   [-0.1, 0],
</code></pre></p><p style="background: #eeeeee; margin-left: 24pt"><pre><code>              [0.1, 0.1], [0, 0],
</code></pre></p><p style="background: #eeeeee; margin-left: 24pt"><pre><code>              [1, 1],     [1.1, 1],
</code></pre></p><p style="background: #eeeeee; margin-left: 24pt"><pre><code>              [1, 1.1],   [1.1, 1.1]])
</code></pre></p><p style="background: #eeeeee; margin-left: 24pt">
 </p><p style="background: #eeeeee; margin-left: 24pt"><pre><code>C = ['A','A','A','A','B','B','B','B']
</code></pre></p><p style="background: #eeeeee; margin-left: 24pt">
 </p><p style="background: #eeeeee; margin-left: 24pt"><pre><code># 初始化
</code></pre></p><p style="background: #eeeeee; margin-left: 24pt"><pre><code>clf = neighbors.KNeighborsClassifier(n_neighbors=3, weights="uniform")
</code></pre></p><p style="background: #eeeeee; margin-left: 24pt">
 </p><p style="background: #eeeeee; margin-left: 24pt"><pre><code># 训练
</code></pre></p><p style="background: #eeeeee; margin-left: 24pt"><pre><code>clf.fit(X, C)
</code></pre></p><p style="background: #eeeeee; margin-left: 24pt">
 </p><p style="background: #eeeeee; margin-left: 24pt"><pre><code># 分类
</code></pre></p><p style="background: #eeeeee; margin-left: 24pt"><pre><code>c = clf.predict(np.array([[0.9,0.8]]))
</code></pre></p><p style="background: #eeeeee; margin-left: 24pt"><pre><code>print(c)
</code></pre></p><p><span style="font-family:宋体; font-size:12pt">上面的例子可以将k近邻算法分成三步，初始化、训练和分类。初始化可设置参数，本文涉及到的参数有：
</span></p><ul><li>n_neighbors: 指参数k
</li><li>weights: 指定数据分类的权重，<em>归一化</em> 是其中的一个方式。
</li><li>algorithm: 该参数可设定使用kd-tree等方法。
</li><li>metric: 距离计算公式
</li></ul><h1>参考资料
</h1><ul><li>《Machine Learning in Action》第2章
</li><li><a href="https://en.wikipedia.org/wiki/K-nearest_neighbors_algorithm">https://en.wikipedia.org/wiki/K-nearest_neighbors_algorithm</a>
		</li><li><a href="https://code.csdn.net/lemene/zxml/tree/master">https://code.csdn.net/lemene/zxml/tree/master</a>
		</li><li><a href="http://scikit-learn.org/stable/modules/neighbors.html">http://scikit-learn.org/stable/modules/neighbors.html</a></li></ul><img src ="http://www.cppblog.com/lemene/aggbug/214366.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/lemene/" target="_blank">lemene</a> 2016-10-28 16:18 <a href="http://www.cppblog.com/lemene/archive/2016/10/28/214366.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>title</title><link>http://www.cppblog.com/lemene/archive/2016/10/28/214365.html</link><dc:creator>lemene</dc:creator><author>lemene</author><pubDate>Fri, 28 Oct 2016 07:36:00 GMT</pubDate><guid>http://www.cppblog.com/lemene/archive/2016/10/28/214365.html</guid><wfw:comment>http://www.cppblog.com/lemene/comments/214365.html</wfw:comment><comments>http://www.cppblog.com/lemene/archive/2016/10/28/214365.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/lemene/comments/commentRss/214365.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/lemene/services/trackbacks/214365.html</trackback:ping><description><![CDATA[description<img src ="http://www.cppblog.com/lemene/aggbug/214365.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/lemene/" target="_blank">lemene</a> 2016-10-28 15:36 <a href="http://www.cppblog.com/lemene/archive/2016/10/28/214365.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>CPPEXP —— 构造函数抛异常</title><link>http://www.cppblog.com/lemene/archive/2016/04/30/213391.html</link><dc:creator>lemene</dc:creator><author>lemene</author><pubDate>Sat, 30 Apr 2016 02:17:00 GMT</pubDate><guid>http://www.cppblog.com/lemene/archive/2016/04/30/213391.html</guid><wfw:comment>http://www.cppblog.com/lemene/comments/213391.html</wfw:comment><comments>http://www.cppblog.com/lemene/archive/2016/04/30/213391.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/lemene/comments/commentRss/213391.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/lemene/services/trackbacks/213391.html</trackback:ping><description><![CDATA[<div id="MathJax_Message" style="display: none;"></div><h2 id="wiz_toc_0">说明</h2>

<p>类的构造函数抛出异常，不会调用该类的析构函数，资源的释放原则是编译器申请的编译器负责，程序员申请的程序员负责。 <br>
在实验代码中，子类Except的构造函数抛出异常，则Base和mMember1的构造函数是编译器调用，因此编译器会调用它们的析构函数，而mMember2由程序员主动使用new生成，因此需要程序员主动使用delete。</p>

<p>解决方法：</p>

<ol>
<li>在构造函数中使用<code>try...catch</code>结构</li>
<li>使用类包装资源申请，如auto_ptr。</li>
</ol>

<h2 id="wiz_toc_1">实验代码</h2>

<pre class="prettyprint linenums prettyprinted" style=""><ol class="linenums"><li class="L0"><code class="language-C"><span class="com">/** </span></code></li><li class="L1"><code class="language-C"><span class="com"> * @file constructor_exception.cpp</span></code></li><li class="L2"><code class="language-C"><span class="com"> * @brief 测试构造函数异常引起的行为</span></code></li><li class="L3"><code class="language-C"><span class="com"> * @copyright public domain</span></code></li><li class="L4"><code class="language-C"><span class="com"> */</span></code></li><li class="L5"><code class="language-C"></code></li><li class="L6"><code class="language-C"><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;iostream&gt;</span></code></li><li class="L7"><code class="language-C"><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;exception&gt;</span></code></li><li class="L8"><code class="language-C"><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;memory&gt;</span></code></li><li class="L9"><code class="language-C"><span class="kwd">class</span><span class="pln"> </span><span class="typ">Base</span><span class="pln"> </span><span class="pun">{</span></code></li><li class="L0"><code class="language-C"><span class="kwd">public</span><span class="pun">:</span></code></li><li class="L1"><code class="language-C"><span class="typ">Base</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"Base()"</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln"> </span><span class="pun">}</span></code></li><li class="L2"><code class="language-C"><span class="kwd">virtual</span><span class="pln"> </span><span class="pun">~</span><span class="typ">Base</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"~Base()"</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln"> </span><span class="pun">}</span></code></li><li class="L3"><code class="language-C"><span class="pun">};</span></code></li><li class="L4"><code class="language-C"></code></li><li class="L5"><code class="language-C"><span class="kwd">class</span><span class="pln"> </span><span class="typ">Member</span><span class="pln"> </span><span class="pun">{</span></code></li><li class="L6"><code class="language-C"><span class="kwd">public</span><span class="pun">:</span></code></li><li class="L7"><code class="language-C"><span class="typ">Member</span><span class="pun">(</span><span class="kwd">int</span><span class="pln"> id</span><span class="pun">):</span><span class="pln">mId</span><span class="pun">(</span><span class="pln">id</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"Member():"</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> mId </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln"> </span><span class="pun">}</span></code></li><li class="L8"><code class="language-C"><span class="kwd">virtual</span><span class="pln"> </span><span class="pun">~</span><span class="typ">Member</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"~Member()"</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> mId </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln"> </span><span class="pun">}</span></code></li><li class="L9"><code class="language-C"><span class="kwd">protected</span><span class="pun">:</span></code></li><li class="L0"><code class="language-C"><span class="kwd">int</span><span class="pln"> mId</span><span class="pun">;</span></code></li><li class="L1"><code class="language-C"><span class="pun">};</span></code></li><li class="L2"><code class="language-C"></code></li><li class="L3"><code class="language-C"><span class="kwd">class</span><span class="pln"> </span><span class="typ">Except</span><span class="pln"> </span><span class="pun">:</span><span class="pln"> </span><span class="kwd">public</span><span class="pln"> </span><span class="typ">Base</span><span class="pln"> </span><span class="pun">{</span></code></li><li class="L4"><code class="language-C"><span class="kwd">public</span><span class="pun">:</span></code></li><li class="L5"><code class="language-C"><span class="typ">Except</span><span class="pun">()</span><span class="pln"> </span><span class="pun">:</span><span class="pln"> mMember1</span><span class="pun">(</span><span class="lit">1</span><span class="pun">),</span><span class="pln"> mMember2</span><span class="pun">(</span><span class="pln">NULL</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span></code></li><li class="L6"><code class="language-C"><span class="pln">std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"Except() enter"</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln"> </span></code></li><li class="L7"><code class="language-C"><span class="pln">mMember2 </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Member</span><span class="pun">(</span><span class="lit">2</span><span class="pun">);</span></code></li><li class="L8"><code class="language-C"><span class="pln">mMember3</span><span class="pun">.</span><span class="pln">reset</span><span class="pun">(</span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Member</span><span class="pun">(</span><span class="lit">3</span><span class="pun">));</span></code></li><li class="L9"><code class="language-C"><span class="kwd">throw</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">exception</span><span class="pun">();</span></code></li><li class="L0"><code class="language-C"><span class="pln">std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"Except() leave"</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln"> </span></code></li><li class="L1"><code class="language-C"><span class="pun">}</span></code></li><li class="L2"><code class="language-C"></code></li><li class="L3"><code class="language-C"><span class="kwd">virtual</span><span class="pln"> </span><span class="pun">~</span><span class="typ">Except</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span></code></li><li class="L4"><code class="language-C"><span class="kwd">delete</span><span class="pln"> mMember2</span><span class="pun">;</span></code></li><li class="L5"><code class="language-C"><span class="pln">std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"~Except()"</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln"> </span></code></li><li class="L6"><code class="language-C"><span class="pun">}</span></code></li><li class="L7"><code class="language-C"></code></li><li class="L8"><code class="language-C"><span class="kwd">protected</span><span class="pun">:</span></code></li><li class="L9"><code class="language-C"><span class="typ">Member</span><span class="pln"> mMember1</span><span class="pun">;</span></code></li><li class="L0"><code class="language-C"><span class="typ">Member</span><span class="pln"> </span><span class="pun">*</span><span class="pln">mMember2</span><span class="pun">;</span></code></li><li class="L1"><code class="language-C"><span class="pln">std</span><span class="pun">::</span><span class="pln">auto_ptr</span><span class="pun">&lt;</span><span class="typ">Member</span><span class="pun">&gt;</span><span class="pln"> mMember3</span><span class="pun">;</span></code></li><li class="L2"><code class="language-C"><span class="pun">};</span></code></li><li class="L3"><code class="language-C"></code></li><li class="L4"><code class="language-C"><span class="kwd">int</span><span class="pln"> main</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span></code></li><li class="L5"><code class="language-C"><span class="kwd">try</span><span class="pln"> </span><span class="pun">{</span></code></li><li class="L6"><code class="language-C"><span class="typ">Except</span><span class="pln"> e</span><span class="pun">;</span></code></li><li class="L7"><code class="language-C"><span class="pun">}</span><span class="pln"> </span><span class="kwd">catch</span><span class="pln"> </span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">exception</span><span class="pun">&amp;</span><span class="pln"> e</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span></code></li><li class="L8"><code class="language-C"><span class="pln">std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> e</span><span class="pun">.</span><span class="pln">what</span><span class="pun">()</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span></code></li><li class="L9"><code class="language-C"><span class="pun">}</span></code></li><li class="L0"><code class="language-C"></code></li><li class="L1"><code class="language-C"><span class="kwd">return</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span></code></li><li class="L2"><code class="language-C"><span class="pun">}</span></code></li></ol></pre>

<h2 id="wiz_toc_2">运行及结果</h2>

<pre><code>$ g++ constructor_exception.cpp 
$ ./a.out 
Base()
Member():1
Except() enter
Member():2
Member():3
~Member()3
~Member()1
~Base()
std::exception
</code></pre><br /><br /><div><a title="来自为知笔记(Wiz)" href="http://www.wiz.cn/i/b9bfd344">来自为知笔记(Wiz)</a></div><br /><br /><img src ="http://www.cppblog.com/lemene/aggbug/213391.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/lemene/" target="_blank">lemene</a> 2016-04-30 10:17 <a href="http://www.cppblog.com/lemene/archive/2016/04/30/213391.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>CPPEXP —— 构造析构函数调用顺序</title><link>http://www.cppblog.com/lemene/archive/2016/04/23/213349.html</link><dc:creator>lemene</dc:creator><author>lemene</author><pubDate>Sat, 23 Apr 2016 10:26:00 GMT</pubDate><guid>http://www.cppblog.com/lemene/archive/2016/04/23/213349.html</guid><wfw:comment>http://www.cppblog.com/lemene/comments/213349.html</wfw:comment><comments>http://www.cppblog.com/lemene/archive/2016/04/23/213349.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/lemene/comments/commentRss/213349.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/lemene/services/trackbacks/213349.html</trackback:ping><description><![CDATA[<p>## 说明</p><p>构造函数的调用顺序是先父类再子类。析构函数的顺序相反——先子类再父类。有继承关系的类的析构函数需要声明为virtual，但并非必须。声明virtual表明函数不能再编译期间确定，只有在运行时才能确定。这样的场景是删除基类指针，但其指向是派生类。此时编译器看到的只有基类信息，如果没有声明virtual，就没有虚函数表或者虚函数表没有析构函数项，只能调用基类的析构函数。如果不声明virtual，将子类指针赋值给父类指针是有风险的操作。</p><p><br></p><p><br></p><p>## 实验代码</p><p><br></p><p>```C</p><p><span ></span></p><p><span ></span></p><p>/**</p><p>&nbsp;* @file constructor_destructor_sequence.cpp</p><p>&nbsp;* @brief 测试构造析构函数的调用次序</p><p>&nbsp;* @copyright public domain</p><p>&nbsp;*/</p><p><br></p><p>#include &lt;iostream&gt;</p><p><br></p><p>class Base {</p><p>public:</p><p><span >&nbsp; &nbsp;&nbsp;</span>Base() { std::cout &lt;&lt; "Base()" &lt;&lt; std::endl; }</p><p><span >&nbsp; &nbsp;&nbsp;</span>~Base() { std::cout &lt;&lt; "~Base()" &lt;&lt; std::endl; }</p><p>};</p><p><br></p><p>class VBase {</p><p>public:</p><p><span >&nbsp; &nbsp;&nbsp;</span>VBase() { std::cout &lt;&lt; "VBase()" &lt;&lt; std::endl; }</p><p><span >&nbsp; &nbsp;&nbsp;</span>virtual ~VBase() { std::cout &lt;&lt; "~VBase()" &lt;&lt; std::endl; }</p><p>};</p><p><br></p><p>class Derived : public Base {</p><p>public:</p><p><span >&nbsp; &nbsp;&nbsp;</span>Derived() { std::cout &lt;&lt; "Derived()" &lt;&lt; std::endl; }</p><p><span >&nbsp; &nbsp;&nbsp;</span>~Derived() { std::cout &lt;&lt; "~Derived()" &lt;&lt; std::endl; }</p><p>};</p><p><br></p><p>class VDerived: public VBase {</p><p>public:</p><p><span >&nbsp; &nbsp;&nbsp;</span>Derived() { std::cout &lt;&lt; "VDerived()" &lt;&lt; std::endl; }</p><p><span >&nbsp; &nbsp;&nbsp;</span>~VDerived() { std::cout &lt;&lt; "~VDerived()" &lt;&lt; std::endl; }</p><p>};</p><p><br></p><p>void test_0() {</p><p><span >&nbsp; &nbsp;&nbsp;</span>std::cout &lt;&lt;"子类不声明virtual，按基类指针删除派生类" &lt;&lt; std::endl;</p><p><span >&nbsp; &nbsp;&nbsp;</span>VBase* p = new VDerived;</p><p><span >&nbsp; &nbsp;&nbsp;</span>delete p;</p><p>}</p><p><br></p><p>void test_1() {</p><p><span >&nbsp; &nbsp;&nbsp;</span>std::cout &lt;&lt;"不声明virtual，按派生类指针删除派生类" &lt;&lt; std::endl;</p><p><span >&nbsp; &nbsp;&nbsp;</span>Derived* p = new Derived;</p><p><span >&nbsp; &nbsp;&nbsp;</span>delete p;</p><p>}</p><p><br></p><p>void test_2() {</p><p><span >&nbsp; &nbsp;&nbsp;</span>std::cout &lt;&lt;"不声明virtual，按基类指针删除派生类" &lt;&lt; std::endl;</p><p><span >&nbsp; &nbsp;&nbsp;</span>Base* p = new Derived;</p><p><span >&nbsp; &nbsp;&nbsp;</span>delete p;</p><p>}</p><p><br></p><p>void test_3() {</p><p><span >&nbsp; &nbsp;&nbsp;</span>std::cout &lt;&lt;"不声明virtual，按void*删除派生类" &lt;&lt; std::endl;</p><p><span >&nbsp; &nbsp;&nbsp;</span>void* p = new Derived;</p><p><span >&nbsp; &nbsp;&nbsp;</span>delete p;</p><p>}</p><p><br></p><p>int main() {</p><p>&nbsp; &nbsp; test_0();</p><p><span >&nbsp; &nbsp;&nbsp;</span>test_1();</p><p><span >&nbsp; &nbsp;&nbsp;</span>test_2();</p><p><span >&nbsp; &nbsp;&nbsp;</span>test_3();</p><p><br></p><p><span >&nbsp; &nbsp;&nbsp;</span>return 0;</p><p>}</p><p>```</p><p><br></p><p>## 运行及结果<br></p><p><br></p><p><span >&nbsp; &nbsp; &gt; g++&nbsp;</span><span >constructor_destructor_sequence.cpp</span><br></p><p></p><p><span >&nbsp; &nbsp;&nbsp;</span>constructor_destructor_sequence.cpp: In function 'void test_3()':</p><p><span >&nbsp; &nbsp;&nbsp;</span>constructor_destructor_sequence.cpp:54:9: warning: deleting 'void*' is undefined [enabled by default]</p><p><br></p><p><span >&nbsp; &nbsp;&nbsp;</span>&gt; a.exe</p><p><span >&nbsp; &nbsp;&nbsp;</span>子类不声明virtual，按基类指针删除派生类</p><p><span >&nbsp; &nbsp;&nbsp;</span>VBase()</p><p><span >&nbsp; &nbsp;&nbsp;</span>VDerived()</p><p><span >&nbsp; &nbsp;&nbsp;</span>~VDerived()</p><p><span >&nbsp; &nbsp;&nbsp;</span>~VBase()</p><p><span >&nbsp; &nbsp;&nbsp;</span>不声明virtual，按派生类指针删除派生类</p><p><span >&nbsp; &nbsp;&nbsp;</span>Base()</p><p><span >&nbsp; &nbsp;&nbsp;</span>Derived()</p><p><span >&nbsp; &nbsp;&nbsp;</span>~Derived()</p><p><span >&nbsp; &nbsp;&nbsp;</span>~Base()</p><p><span >&nbsp; &nbsp;&nbsp;</span>不声明virtual，按基类指针删除派生类</p><p><span >&nbsp; &nbsp;&nbsp;</span>Base()</p><p><span >&nbsp; &nbsp;&nbsp;</span>Derived()</p><p><span >&nbsp; &nbsp;&nbsp;</span>~Base()</p><p><span >&nbsp; &nbsp;&nbsp;</span>不声明virtual，按void*删除派生类</p><p><span >&nbsp; &nbsp;&nbsp;</span>Base()</p><p><span >&nbsp; &nbsp;&nbsp;</span>Derived()</p><p><br></p><p><br></p><p></p><p></p><br /><br /><div><a title="来自为知笔记(Wiz)" href="http://www.wiz.cn/i/b9bfd344">来自为知笔记(Wiz)</a></div><br /><br /><img src ="http://www.cppblog.com/lemene/aggbug/213349.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/lemene/" target="_blank">lemene</a> 2016-04-23 18:26 <a href="http://www.cppblog.com/lemene/archive/2016/04/23/213349.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>CPPEXP —— char[]和char*的区别</title><link>http://www.cppblog.com/lemene/archive/2016/04/20/213315.html</link><dc:creator>lemene</dc:creator><author>lemene</author><pubDate>Wed, 20 Apr 2016 13:51:00 GMT</pubDate><guid>http://www.cppblog.com/lemene/archive/2016/04/20/213315.html</guid><wfw:comment>http://www.cppblog.com/lemene/comments/213315.html</wfw:comment><comments>http://www.cppblog.com/lemene/archive/2016/04/20/213315.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/lemene/comments/commentRss/213315.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/lemene/services/trackbacks/213315.html</trackback:ping><description><![CDATA[<div id="MathJax_Message" style="display: none;"></div><h2 id="wiz_toc_0">说明</h2>

<p>使用<code>char[]</code>和<code>char*</code>定义变量，并赋值字符串常量，这两者有较大区别。前者定义数组，并将字符串常量拷贝至该数组，变量表示这个新数组的首地址。后者定义指针，指向一个字符常量。前者会产生新的字符串数据，并且拥有读写权限，后者不一定产生新字符串数据，并且只有读权限。</p>

<h2 id="wiz_toc_1">实验代码</h2>

<pre class="prettyprint linenums prettyprinted" style=""><ol class="linenums"><li class="L0"><code class="language-C"><span class="com">/**</span></code></li><li class="L1"><code class="language-C"><span class="com"> * @file char_array_pointer.cpp</span></code></li><li class="L2"><code class="language-C"><span class="com"> * @brief 测试字符数组和指针</span></code></li><li class="L3"><code class="language-C"><span class="com"> * @copyrigh public domain</span></code></li><li class="L4"><code class="language-C"><span class="com"> */</span></code></li><li class="L5"><code class="language-C"></code></li><li class="L6"><code class="language-C"><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;iostream&gt;</span></code></li><li class="L7"><code class="language-C"></code></li><li class="L8"><code class="language-C"><span class="kwd">const</span><span class="pln"> </span><span class="kwd">char</span><span class="pun">*</span><span class="pln"> string0</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span></code></li><li class="L9"><code class="language-C"><span class="kwd">const</span><span class="pln"> </span><span class="kwd">char</span><span class="pun">*</span><span class="pln"> str </span><span class="pun">=</span><span class="pln"> </span><span class="str">"string"</span><span class="pun">;</span></code></li><li class="L0"><code class="language-C"><span class="kwd">return</span><span class="pln"> str</span><span class="pun">;</span></code></li><li class="L1"><code class="language-C"><span class="pun">}</span></code></li><li class="L2"><code class="language-C"></code></li><li class="L3"><code class="language-C"><span class="kwd">const</span><span class="pln"> </span><span class="kwd">char</span><span class="pun">*</span><span class="pln"> string1</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span></code></li><li class="L4"><code class="language-C"><span class="kwd">return</span><span class="pln"> </span><span class="str">"string"</span><span class="pun">;</span></code></li><li class="L5"><code class="language-C"><span class="pun">}</span></code></li><li class="L6"><code class="language-C"></code></li><li class="L7"><code class="language-C"><span class="kwd">const</span><span class="pln"> </span><span class="kwd">char</span><span class="pun">*</span><span class="pln"> string2</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span></code></li><li class="L8"><code class="language-C"><span class="kwd">static</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> </span><span class="kwd">char</span><span class="pln"> str</span><span class="pun">[]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="str">"string"</span><span class="pun">;</span></code></li><li class="L9"><code class="language-C"><span class="kwd">return</span><span class="pln"> str</span><span class="pun">;</span></code></li><li class="L0"><code class="language-C"><span class="pun">}</span></code></li><li class="L1"><code class="language-C"></code></li><li class="L2"><code class="language-C"><span class="kwd">const</span><span class="pln"> </span><span class="kwd">char</span><span class="pun">*</span><span class="pln"> string3</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span></code></li><li class="L3"><code class="language-C"><span class="pln">    </span><span class="kwd">char</span><span class="pln"> str</span><span class="pun">[]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="str">"string"</span><span class="pun">;</span></code></li><li class="L4"><code class="language-C"><span class="pln">    </span><span class="kwd">return</span><span class="pln"> str</span><span class="pun">;</span></code></li><li class="L5"><code class="language-C"><span class="pun">}</span></code></li><li class="L6"><code class="language-C"></code></li><li class="L7"><code class="language-C"><span class="kwd">void</span><span class="pln"> </span><span class="kwd">function</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span></code></li><li class="L8"><code class="language-C"><span class="pln">    </span><span class="kwd">char</span><span class="pln"> a</span><span class="pun">[]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="str">"abc123456"</span><span class="pun">;</span></code></li><li class="L9"><code class="language-C"><span class="pun">}</span></code></li><li class="L0"><code class="language-C"></code></li><li class="L1"><code class="language-C"><span class="kwd">void</span><span class="pln"> test_string1</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span></code></li><li class="L2"><code class="language-C"><span class="pln">    </span><span class="kwd">const</span><span class="pln"> </span><span class="kwd">char</span><span class="pun">*</span><span class="pln"> str </span><span class="pun">=</span><span class="pln"> string1</span><span class="pun">();</span></code></li><li class="L3"><code class="language-C"><span class="pln">    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"test_string1: "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> str </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span></code></li><li class="L4"><code class="language-C"><span class="pln">    </span><span class="kwd">function</span><span class="pun">();</span></code></li><li class="L5"><code class="language-C"><span class="pln">    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"test_string1: "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> str </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span></code></li><li class="L6"><code class="language-C"><span class="pun">}</span></code></li><li class="L7"><code class="language-C"></code></li><li class="L8"><code class="language-C"><span class="kwd">void</span><span class="pln"> test_string2</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span></code></li><li class="L9"><code class="language-C"><span class="pln">    </span><span class="kwd">const</span><span class="pln"> </span><span class="kwd">char</span><span class="pun">*</span><span class="pln"> str </span><span class="pun">=</span><span class="pln"> string2</span><span class="pun">();</span></code></li><li class="L0"><code class="language-C"><span class="pln">    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"test_string2: "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> str </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span></code></li><li class="L1"><code class="language-C"><span class="pln">    </span><span class="kwd">function</span><span class="pun">();</span></code></li><li class="L2"><code class="language-C"><span class="pln">    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"test_string2: "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> str </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span></code></li><li class="L3"><code class="language-C"><span class="pun">}</span></code></li><li class="L4"><code class="language-C"></code></li><li class="L5"><code class="language-C"><span class="kwd">void</span><span class="pln"> test_string3</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span></code></li><li class="L6"><code class="language-C"><span class="pln">    </span><span class="kwd">const</span><span class="pln"> </span><span class="kwd">char</span><span class="pun">*</span><span class="pln"> str </span><span class="pun">=</span><span class="pln"> string3</span><span class="pun">();</span></code></li><li class="L7"><code class="language-C"><span class="pln">    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"test_string3: "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> str </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span></code></li><li class="L8"><code class="language-C"><span class="pln">    </span><span class="kwd">function</span><span class="pun">();</span></code></li><li class="L9"><code class="language-C"><span class="pln">    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"test_string3: "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> str </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span></code></li><li class="L0"><code class="language-C"><span class="pun">}</span></code></li><li class="L1"><code class="language-C"></code></li><li class="L2"><code class="language-C"><span class="kwd">int</span><span class="pln"> main</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span></code></li><li class="L3"><code class="language-C"></code></li><li class="L4"><code class="language-C"><span class="pln">std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"string0 == string1 is "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="pun">(</span><span class="pln">string0</span><span class="pun">()</span><span class="pln"> </span><span class="pun">==</span><span class="pln"> string1</span><span class="pun">()</span><span class="pln"> </span><span class="pun">?</span><span class="pln"> </span><span class="str">"true"</span><span class="pln"> </span><span class="pun">:</span><span class="pln"> </span><span class="str">"false"</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span></code></li><li class="L5"><code class="language-C"></code></li><li class="L6"><code class="language-C"><span class="pln">std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"string1 == string2 is "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="pun">(</span><span class="pln">string1</span><span class="pun">()</span><span class="pln"> </span><span class="pun">==</span><span class="pln"> string2</span><span class="pun">()</span><span class="pln"> </span><span class="pun">?</span><span class="pln"> </span><span class="str">"true"</span><span class="pln"> </span><span class="pun">:</span><span class="pln"> </span><span class="str">"false"</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span></code></li><li class="L7"><code class="language-C"></code></li><li class="L8"><code class="language-C"><span class="pln">    test_string1</span><span class="pun">();</span></code></li><li class="L9"><code class="language-C"><span class="pln">    test_string2</span><span class="pun">();</span></code></li><li class="L0"><code class="language-C"><span class="pln">    test_string3</span><span class="pun">();</span></code></li><li class="L1"><code class="language-C"></code></li><li class="L2"><code class="language-C"><span class="pln">    </span><span class="kwd">return</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span></code></li><li class="L3"><code class="language-C"><span class="pun">}</span></code></li></ol></pre>

<h2 id="wiz_toc_2">运行及结果</h2>

<pre><code>$ g++ char_array_pointer.cpp
char_array_pointer.cpp: In function 'const char* string3()':
char_array_pointer.cpp:24:10: warning: address of local variable 'str' returned [enabled by default]

$ ./a.exe
string0 == string1 is true
string1 == string2 is false
test_string1: string
test_string1: string
test_string2: string
test_string2: string
test_string3: string
test_string3: abc12345YP@
</code></pre><br /><br /><div><a title="来自为知笔记(Wiz)" href="http://www.wiz.cn/i/b9bfd344">来自为知笔记(Wiz)</a></div><br /><br /><img src ="http://www.cppblog.com/lemene/aggbug/213315.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/lemene/" target="_blank">lemene</a> 2016-04-20 21:51 <a href="http://www.cppblog.com/lemene/archive/2016/04/20/213315.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>CPPEXP —— 字符串常量</title><link>http://www.cppblog.com/lemene/archive/2016/04/19/213309.html</link><dc:creator>lemene</dc:creator><author>lemene</author><pubDate>Tue, 19 Apr 2016 12:51:00 GMT</pubDate><guid>http://www.cppblog.com/lemene/archive/2016/04/19/213309.html</guid><wfw:comment>http://www.cppblog.com/lemene/comments/213309.html</wfw:comment><comments>http://www.cppblog.com/lemene/archive/2016/04/19/213309.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/lemene/comments/commentRss/213309.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/lemene/services/trackbacks/213309.html</trackback:ping><description><![CDATA[<div id="MathJax_Message" style="display: none;"></div><h2 id="wiz_toc_0">说明</h2>

<p>字符串常量会放入程序的静态区，并且是只读数据段。由于是只读数据，编译器会合并相同的字符串常量。</p>

<h2 id="wiz_toc_1">实验代码</h2>

<pre class="prettyprint linenums prettyprinted" style=""><ol class="linenums"><li class="L0"><code class="language-c"></code></li><li class="L1"><code class="language-c"><span class="com">/**</span></code></li><li class="L2"><code class="language-c"><span class="com"> * @file constant_string.cpp</span></code></li><li class="L3"><code class="language-c"><span class="com"> * @brief 测试常量字符串</span></code></li><li class="L4"><code class="language-c"><span class="com"> * @copyright public domain</span></code></li><li class="L5"><code class="language-c"><span class="com"> */</span></code></li><li class="L6"><code class="language-c"></code></li><li class="L7"><code class="language-c"><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;iostream&gt;</span></code></li><li class="L8"><code class="language-c"></code></li><li class="L9"><code class="language-c"><span class="typ">int</span><span class="pln"> main</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span></code></li><li class="L0"><code class="language-c"><span class="pln">    </span><span class="kwd">char</span><span class="pun">*</span><span class="pln"> a </span><span class="pun">=</span><span class="pln"> </span><span class="str">"string"</span><span class="pun">;</span></code></li><li class="L1"><code class="language-c"><span class="pln">    </span><span class="kwd">const</span><span class="pln"> </span><span class="kwd">char</span><span class="pun">*</span><span class="pln"> b </span><span class="pun">=</span><span class="pln"> </span><span class="str">"string"</span><span class="pun">;</span></code></li><li class="L2"><code class="language-c"></code></li><li class="L3"><code class="language-c"><span class="pln">    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"a == b is "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="pun">(</span><span class="pln">a</span><span class="pun">==</span><span class="pln">b </span><span class="pun">?</span><span class="pln"> </span><span class="str">"true"</span><span class="pln"> </span><span class="pun">:</span><span class="pln"> </span><span class="str">"false"</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span></code></li><li class="L4"><code class="language-c"></code></li><li class="L5"><code class="language-c"><span class="pln">    a</span><span class="pun">[</span><span class="lit">1</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="str">'d'</span><span class="pun">;</span><span class="pln"> </span><span class="com">// ERROR</span></code></li><li class="L6"><code class="language-c"></code></li><li class="L7"><code class="language-c"><span class="pln">    </span><span class="kwd">return</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span></code></li><li class="L8"><code class="language-c"><span class="pun">}</span></code></li></ol></pre>

<h2 id="wiz_toc_2">运行及结果</h2>

<pre><code>$ g++ constant_string.cpp 
constant_string.cpp: In function ‘int main()’:
constant_string.cpp:10:12: warning: deprecated conversion from string constant to ‘char*’ [-Wwrite-strings]
  char* a = "string";
            ^
$ ./a.out 
a == b is true
段错误 (核心已转储)
</code></pre>

<ul>
<li><code>a</code>和<code>b</code>的地址相同。</li>
<li>编译器会对<code>char* a = "string"</code>报警告。</li>
<li>对字符串常量的修改会引发程序异常。</li>
</ul><br /><br /><div><a title="来自为知笔记(Wiz)" href="http://www.wiz.cn/i/b9bfd344">来自为知笔记(Wiz)</a></div><br /><br /><img src ="http://www.cppblog.com/lemene/aggbug/213309.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/lemene/" target="_blank">lemene</a> 2016-04-19 20:51 <a href="http://www.cppblog.com/lemene/archive/2016/04/19/213309.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>CPPEXP —— 字节序（大小端）</title><link>http://www.cppblog.com/lemene/archive/2016/04/19/213308.html</link><dc:creator>lemene</dc:creator><author>lemene</author><pubDate>Tue, 19 Apr 2016 12:39:00 GMT</pubDate><guid>http://www.cppblog.com/lemene/archive/2016/04/19/213308.html</guid><wfw:comment>http://www.cppblog.com/lemene/comments/213308.html</wfw:comment><comments>http://www.cppblog.com/lemene/archive/2016/04/19/213308.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/lemene/comments/commentRss/213308.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/lemene/services/trackbacks/213308.html</trackback:ping><description><![CDATA[<div id="MathJax_Message" style="display: none;"></div><h2 id="wiz_toc_0">说明</h2>

<p>big endian和little endian表示如何存放多字节数据。前者低位字节排放在内存的高端，后者相反。将unsigned long数据强制转换成unsigned char*数据，则它们在两种模式下的对应关系如下：</p>

<p>big endian：</p>

<pre><code>ul = (uc[0]&lt;&lt; 24) + (uc[1]&lt;&lt;16) + (uc[2]&lt;&lt;8) + uc[3];
</code></pre>

<p>little endian:</p>

<pre><code>ul = (uc[3]&lt;&lt;24) + (uc[2]&lt;&lt;16) + (uc[1]&lt;&lt;8) + uc[0];
</code></pre>

<h2 id="wiz_toc_1">实验代码</h2>

<pre class="prettyprint linenums prettyprinted" style=""><ol class="linenums"><li class="L0"><code class="language-c"><span class="com">/**</span></code></li><li class="L1"><code class="language-c"><span class="com"> * @file little_big_endian.cpp</span></code></li><li class="L2"><code class="language-c"><span class="com"> * @brief 测试大小端字节序</span></code></li><li class="L3"><code class="language-c"><span class="com"> * @copyright public domain</span></code></li><li class="L4"><code class="language-c"><span class="com"> */</span></code></li><li class="L5"><code class="language-c"></code></li><li class="L6"><code class="language-c"><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;iostream&gt;</span></code></li><li class="L7"><code class="language-c"></code></li><li class="L8"><code class="language-c"><span class="kwd">static</span><span class="pln"> </span><span class="kwd">bool</span><span class="pln"> is_little_endian</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span></code></li><li class="L9"><code class="language-c"><span class="kwd">union</span><span class="pln"> </span><span class="pun">{</span></code></li><li class="L0"><code class="language-c"><span class="kwd">long</span><span class="pln"> l</span><span class="pun">;</span></code></li><li class="L1"><code class="language-c"><span class="kwd">char</span><span class="pln"> cs</span><span class="pun">[</span><span class="lit">4</span><span class="pun">];</span></code></li><li class="L2"><code class="language-c"><span class="pun">}</span><span class="pln"> t</span><span class="pun">;</span></code></li><li class="L3"><code class="language-c"></code></li><li class="L4"><code class="language-c"><span class="pln">t</span><span class="pun">.</span><span class="pln">l </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1</span><span class="pun">;</span></code></li><li class="L5"><code class="language-c"></code></li><li class="L6"><code class="language-c"><span class="kwd">return</span><span class="pln"> t</span><span class="pun">.</span><span class="pln">cs</span><span class="pun">[</span><span class="lit">0</span><span class="pun">]</span><span class="pln"> </span><span class="pun">==</span><span class="pln"> </span><span class="lit">1</span><span class="pun">;</span></code></li><li class="L7"><code class="language-c"><span class="pun">}</span></code></li><li class="L8"><code class="language-c"></code></li><li class="L9"><code class="language-c"><span class="typ">int</span><span class="pln"> main</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span></code></li><li class="L0"><code class="language-c"><span class="kwd">unsigned</span><span class="pln"> </span><span class="kwd">long</span><span class="pln"> ul </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0x12345678</span><span class="pun">;</span></code></li><li class="L1"><code class="language-c"><span class="kwd">unsigned</span><span class="pln"> </span><span class="kwd">char</span><span class="pun">*</span><span class="pln"> uc </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">unsigned</span><span class="pln"> </span><span class="kwd">char</span><span class="pun">*)&amp;</span><span class="pln">ul</span><span class="pun">;</span></code></li><li class="L2"><code class="language-c"><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">is_little_endian</span><span class="pun">())</span><span class="pln"> </span><span class="pun">{</span></code></li><li class="L3"><code class="language-c"><span class="kwd">bool</span><span class="pln"> r </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="pln">uc</span><span class="pun">[</span><span class="lit">0</span><span class="pun">]</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="pun">(</span><span class="pln">uc</span><span class="pun">[</span><span class="lit">1</span><span class="pun">]&lt;&lt;</span><span class="lit">8</span><span class="pun">)</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="pun">(</span><span class="pln">uc</span><span class="pun">[</span><span class="lit">2</span><span class="pun">]&lt;&lt;</span><span class="lit">16</span><span class="pun">)</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="pun">(</span><span class="pln">uc</span><span class="pun">[</span><span class="lit">3</span><span class="pun">]&lt;&lt;</span><span class="lit">24</span><span class="pun">))</span><span class="pln"> </span><span class="pun">==</span><span class="pln"> ul</span><span class="pun">;</span></code></li><li class="L4"><code class="language-c"><span class="pln">std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"little: (uc[0] + (uc[1]&lt;&lt;8) + (uc[2]&lt;&lt;16) + (uc[3]&lt;&lt;24)) == ul is "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="pun">(</span><span class="pln">r </span><span class="pun">?</span><span class="pln"> </span><span class="str">"true"</span><span class="pln"> </span><span class="pun">:</span><span class="pln"> </span><span class="str">"false"</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span></code></li><li class="L5"><code class="language-c"><span class="pun">}</span><span class="pln"> </span><span class="kwd">else</span><span class="pln"> </span><span class="pun">{</span></code></li><li class="L6"><code class="language-c"><span class="kwd">bool</span><span class="pln"> r </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="pln">uc</span><span class="pun">[</span><span class="lit">3</span><span class="pun">]</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="pun">(</span><span class="pln">uc</span><span class="pun">[</span><span class="lit">2</span><span class="pun">]&lt;&lt;</span><span class="lit">8</span><span class="pun">)</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="pun">(</span><span class="pln">uc</span><span class="pun">[</span><span class="lit">1</span><span class="pun">]&lt;&lt;</span><span class="lit">16</span><span class="pun">)</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="pun">(</span><span class="pln">uc</span><span class="pun">[</span><span class="lit">0</span><span class="pun">]&lt;&lt;</span><span class="lit">24</span><span class="pun">))</span><span class="pln"> </span><span class="pun">==</span><span class="pln"> ul</span><span class="pun">;</span></code></li><li class="L7"><code class="language-c"><span class="pln">std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"little: (uc[3] + (uc[2]&lt;&lt;8) + (uc[1]&lt;&lt;16) + (uc[0]&lt;&lt;24)) == ul is "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="pun">(</span><span class="pln">r </span><span class="pun">?</span><span class="pln"> </span><span class="str">"true"</span><span class="pln"> </span><span class="pun">:</span><span class="pln"> </span><span class="str">"false"</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span></code></li><li class="L8"><code class="language-c"><span class="pun">}</span></code></li><li class="L9"><code class="language-c"></code></li><li class="L0"><code class="language-c"><span class="kwd">return</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span></code></li><li class="L1"><code class="language-c"><span class="pun">}</span></code></li></ol></pre>

<h2 id="wiz_toc_2">运行及结果</h2>

<pre><code>$ g++ little_big_endian.cpp 
$ ./a.out 
little: (uc[0] + (uc[1]&lt;&lt;8) + (uc[2]&lt;&lt;16) + (uc[3]&lt;&lt;24)) == ul is true
</code></pre>

<h2 id="wiz_toc_3">常见问题</h2>

<p>字节序的问题容易出现在不同电脑交互数据的时候，因此当数据输出时——保存成文件或在网络上传输——就应该考虑字节序。</p><br /><br /><div><a title="来自为知笔记(Wiz)" href="http://www.wiz.cn/i/b9bfd344">来自为知笔记(Wiz)</a></div><br /><br /><img src ="http://www.cppblog.com/lemene/aggbug/213308.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/lemene/" target="_blank">lemene</a> 2016-04-19 20:39 <a href="http://www.cppblog.com/lemene/archive/2016/04/19/213308.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>CPPEXP —— 类成员初始化顺序</title><link>http://www.cppblog.com/lemene/archive/2016/04/17/213300.html</link><dc:creator>lemene</dc:creator><author>lemene</author><pubDate>Sun, 17 Apr 2016 04:43:00 GMT</pubDate><guid>http://www.cppblog.com/lemene/archive/2016/04/17/213300.html</guid><wfw:comment>http://www.cppblog.com/lemene/comments/213300.html</wfw:comment><comments>http://www.cppblog.com/lemene/archive/2016/04/17/213300.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/lemene/comments/commentRss/213300.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/lemene/services/trackbacks/213300.html</trackback:ping><description><![CDATA[<div id="MathJax_Message" style="display: none;"></div><h2 id="wiz_toc_0">说明</h2>

<p>C++类成员初始化顺序取决于其声明顺序，而非初始化列表的顺序。</p>

<h2 id="wiz_toc_1">测试代码</h2>

<pre class="prettyprint linenums prettyprinted" style=""><ol class="linenums"><li class="L0"><code class="language-C"><span class="com">/**</span></code></li><li class="L1"><code class="language-C"><span class="com"> * 测试类成员的初始化顺序</span></code></li><li class="L2"><code class="language-C"><span class="com"> * @file init_oder.cpp</span></code></li><li class="L3"><code class="language-C"><span class="com"> */</span></code></li><li class="L4"><code class="language-C"><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;iostream&gt;</span></code></li><li class="L5"><code class="language-C"></code></li><li class="L6"><code class="language-C"><span class="kwd">class</span><span class="pln"> </span><span class="typ">Test</span><span class="pln"> </span><span class="pun">{</span></code></li><li class="L7"><code class="language-C"><span class="kwd">public</span><span class="pun">:</span></code></li><li class="L8"><code class="language-C"><span class="pln">    </span><span class="typ">Test</span><span class="pun">()</span><span class="pln"> </span><span class="pun">:</span><span class="pln"> mBb</span><span class="pun">(</span><span class="pln">sIndex</span><span class="pun">++),</span><span class="pln"> mAa</span><span class="pun">(</span><span class="pln">sIndex</span><span class="pun">++)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="pun">}</span></code></li><li class="L9"><code class="language-C"></code></li><li class="L0"><code class="language-C"><span class="kwd">public</span><span class="pun">:</span></code></li><li class="L1"><code class="language-C"><span class="pln">    </span><span class="kwd">void</span><span class="pln"> </span><span class="typ">Dump</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span></code></li><li class="L2"><code class="language-C"><span class="pln">        std</span><span class="pun">::</span><span class="pln">cout</span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"a: "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> mAa </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">", b: "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> mBb </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span></code></li><li class="L3"><code class="language-C"><span class="pln">    </span><span class="pun">}</span><span class="pln"> </span></code></li><li class="L4"><code class="language-C"></code></li><li class="L5"><code class="language-C"><span class="kwd">protected</span><span class="pun">:</span></code></li><li class="L6"><code class="language-C"><span class="pln">    </span><span class="kwd">int</span><span class="pln"> mAa</span><span class="pun">;</span></code></li><li class="L7"><code class="language-C"><span class="pln">    </span><span class="kwd">int</span><span class="pln"> mBb</span><span class="pun">;</span></code></li><li class="L8"><code class="language-C"></code></li><li class="L9"><code class="language-C"><span class="pln">    </span><span class="kwd">static</span><span class="pln"> </span><span class="kwd">int</span><span class="pln"> sIndex</span><span class="pun">;</span></code></li><li class="L0"><code class="language-C"><span class="pun">};</span></code></li><li class="L1"><code class="language-C"></code></li><li class="L2"><code class="language-C"><span class="kwd">int</span><span class="pln"> </span><span class="typ">Test</span><span class="pun">::</span><span class="pln">sIndex </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1</span><span class="pun">;</span></code></li><li class="L3"><code class="language-C"></code></li><li class="L4"><code class="language-C"><span class="kwd">int</span><span class="pln"> main</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span></code></li><li class="L5"><code class="language-C"><span class="pln">    </span><span class="typ">Test</span><span class="pln"> t</span><span class="pun">;</span></code></li><li class="L6"><code class="language-C"><span class="pln">    t</span><span class="pun">.</span><span class="typ">Dump</span><span class="pun">();</span></code></li><li class="L7"><code class="language-C"><span class="pln">    </span><span class="kwd">return</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span></code></li><li class="L8"><code class="language-C"><span class="pun">}</span></code></li></ol></pre>

<h2 id="wiz_toc_2">运行及结果</h2>

<pre><code>$ g++ init_order.cpp
$ ./a.out
a: 1, b: 2
</code></pre>

<h2 id="wiz_toc_3">风险分析</h2>

<p>当类的成员初始化有依赖关系（如某个成员的构造函数的参数是另一个成员）时，较容易出错。这是因为程序员的意图（初始化列表顺序）和程序的行为（成员声明 顺序）是分离的，前者一般位于实现文件，后者位于头文件，编辑前者往往忽略后者。因此少用有依赖的初始化设计，并且在review中加入该检查条目。</p><br /><br /><div><a title="来自为知笔记(Wiz)" href="http://www.wiz.cn/i/b9bfd344">来自为知笔记(Wiz)</a></div><br /><br /><img src ="http://www.cppblog.com/lemene/aggbug/213300.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/lemene/" target="_blank">lemene</a> 2016-04-17 12:43 <a href="http://www.cppblog.com/lemene/archive/2016/04/17/213300.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>CPPEXP —— 空类的大小</title><link>http://www.cppblog.com/lemene/archive/2016/04/16/213297.html</link><dc:creator>lemene</dc:creator><author>lemene</author><pubDate>Sat, 16 Apr 2016 10:13:00 GMT</pubDate><guid>http://www.cppblog.com/lemene/archive/2016/04/16/213297.html</guid><wfw:comment>http://www.cppblog.com/lemene/comments/213297.html</wfw:comment><comments>http://www.cppblog.com/lemene/archive/2016/04/16/213297.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/lemene/comments/commentRss/213297.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/lemene/services/trackbacks/213297.html</trackback:ping><description><![CDATA[<h2 id="wiz_toc_0">说明</h2>

<ul>
<li>编译器为不含任何成员的空类分配大小为1的空间，这样空类定义的变量地址不会与其相邻定义的变量地址相同。</li>
<li>编译器会在空类的子类中优化掉这多分配的空间。</li>
<li>带虚析构函数的空类不是严格意义的空类，它包含虚函数表指针，因此其大小为指针的大小。</li>
</ul>

<h2 id="wiz_toc_1">实验代码</h2>

<pre class="prettyprint linenums prettyprinted" style=""><ol class="linenums"><li class="L0"><code class="language-C"><span class="com">/**</span></code></li><li class="L1"><code class="language-C"><span class="com"> * @file empty_size.cpp</span></code></li><li class="L2"><code class="language-C"><span class="com"> * @brief 测试空类的大小</span></code></li><li class="L3"><code class="language-C"><span class="com"> * @copyright public domain</span></code></li><li class="L4"><code class="language-C"><span class="com"> */</span></code></li><li class="L5"><code class="language-C"></code></li><li class="L6"><code class="language-C"><span class="com">#include</span><span class="str">&lt;iostream&gt;</span></code></li><li class="L7"><code class="language-C"></code></li><li class="L8"><code class="language-C"><span class="kwd">class</span><span class="pln"> </span><span class="typ">Empty</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="pun">};</span></code></li><li class="L9"><code class="language-C"></code></li><li class="L0"><code class="language-C"><span class="kwd">class</span><span class="pln"> </span><span class="typ">SubEmpty</span><span class="pln"> </span><span class="pun">:</span><span class="pln"> </span><span class="kwd">public</span><span class="pln"> </span><span class="typ">Empty</span></code></li><li class="L1"><code class="language-C"><span class="pun">{</span></code></li><li class="L2"><code class="language-C"><span class="kwd">protected</span><span class="pun">:</span></code></li><li class="L3"><code class="language-C"><span class="pln">    </span><span class="kwd">int</span><span class="pln"> mInt</span><span class="pun">;</span><span class="pln"> </span></code></li><li class="L4"><code class="language-C"><span class="pun">};</span></code></li><li class="L5"><code class="language-C"></code></li><li class="L6"><code class="language-C"><span class="kwd">class</span><span class="pln"> </span><span class="typ">VEmpty</span></code></li><li class="L7"><code class="language-C"><span class="pun">{</span></code></li><li class="L8"><code class="language-C"><span class="kwd">public</span><span class="pun">:</span></code></li><li class="L9"><code class="language-C"><span class="pln">    </span><span class="kwd">virtual</span><span class="pln"> </span><span class="pun">~</span><span class="typ">VEmpty</span><span class="pun">()</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span></code></li><li class="L0"><code class="language-C"><span class="pun">};</span></code></li><li class="L1"><code class="language-C"></code></li><li class="L2"><code class="language-C"></code></li><li class="L3"><code class="language-C"><span class="kwd">int</span><span class="pln"> main</span><span class="pun">()</span><span class="pln"> </span></code></li><li class="L4"><code class="language-C"><span class="pun">{</span></code></li><li class="L5"><code class="language-C"><span class="pln">    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"Empty class: "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="kwd">sizeof</span><span class="pun">(</span><span class="typ">Empty</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span></code></li><li class="L6"><code class="language-C"><span class="pln">    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"SubEmpty: "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="kwd">sizeof</span><span class="pun">(</span><span class="typ">SubEmpty</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span></code></li><li class="L7"><code class="language-C"><span class="pln">    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"VEmpty: "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="kwd">sizeof</span><span class="pun">(</span><span class="typ">VEmpty</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span></code></li><li class="L8"><code class="language-C"><span class="pln">    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"Void*: "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="kwd">sizeof</span><span class="pun">(</span><span class="kwd">void</span><span class="pun">*)</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span></code></li><li class="L9"><code class="language-C"><span class="pln">    </span><span class="kwd">return</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span></code></li><li class="L0"><code class="language-C"><span class="pun">};</span></code></li></ol></pre>

<h2 id="wiz_toc_2">运行及结果</h2>

<pre><code>&gt; g++ empty_size.cpp
&gt; a.exe
Empty class: 1
SubEmpty: 4
VEmpty: 8
Void*: 8
</code></pre><br /><br /><div><a title="来自为知笔记(Wiz)" href="http://www.wiz.cn/i/b9bfd344">来自为知笔记(Wiz)</a></div><br /><br /><img src ="http://www.cppblog.com/lemene/aggbug/213297.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/lemene/" target="_blank">lemene</a> 2016-04-16 18:13 <a href="http://www.cppblog.com/lemene/archive/2016/04/16/213297.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>