﻿<?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++博客-冰山上的狼-文章分类-C++</title><link>http://www.cppblog.com/paladino/category/4425.html</link><description>在努力、磨练、打击下不断地向着理想前进</description><language>zh-cn</language><lastBuildDate>Tue, 20 May 2008 01:11:23 GMT</lastBuildDate><pubDate>Tue, 20 May 2008 01:11:23 GMT</pubDate><ttl>60</ttl><item><title>sizeof 全解析</title><link>http://www.cppblog.com/paladino/articles/26578.html</link><dc:creator>Gu.paladino</dc:creator><author>Gu.paladino</author><pubDate>Mon, 18 Jun 2007 10:26:00 GMT</pubDate><guid>http://www.cppblog.com/paladino/articles/26578.html</guid><wfw:comment>http://www.cppblog.com/paladino/comments/26578.html</wfw:comment><comments>http://www.cppblog.com/paladino/articles/26578.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/paladino/comments/commentRss/26578.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/paladino/services/trackbacks/26578.html</trackback:ping><description><![CDATA[<div class="postTitle">0. 前向声明</div>
<div class="postText">
<p>sizeof，一个其貌不扬的家伙，引无数菜鸟竟折腰，小虾我当初也没少犯迷糊，秉着&#8220;辛苦我一个，幸福千万人&#8221;的伟大思想，我决定将其尽可能详细的总结一下。</p>
<p>但当我总结的时候才发现，这个问题既可以简单，又可以复杂，所以本文有的地方并不适合初学者，甚至都没有必要大作文章。但如果你想&#8220;知其然，更知其所以然&#8221;的话，那么这篇文章对你或许有所帮助。</p>
<p>菜鸟我对C++的掌握尚未深入，其中不乏错误，欢迎各位扔砖砸蛋。</p>
<p>1. 定义</p>
<p>sizeof是何方神圣？sizeof乃C/C++中的一个操作符（operator）是也，简单的说其作用就是返回一个对象或者类型所占的内存字节数。 </p>
<p>MSDN上的解释为：</p>
<div class="postRefrence">
<p>The sizeof keyword gives the amount of storage, in bytes, associated with a variable or a type (including aggregate types).</p>
<p>This keyword returns a value of type size_t.</p>
</div>
<p>其返回值类型为size_t，在头文件stddef.h中定义。这是一个依赖于编译系统的值，一般定义为：</p>
<div class="postCode"><font color="#0000ff">typedef</font>&nbsp;<font color="#0000ff">unsigned</font>&nbsp;<font color="#0000ff">int</font>&nbsp;size_t; </div>
<p>世上编译器林林总总，但作为一个规范，它们都会保证char、signed char和unsigned char的sizeof值为1，毕竟char是我们编程能用的最小数据类型。</p>
<p>2. 语法</p>
<p>sizeof有三种语法形式，如下：</p>
<div class="postConclusion">1) sizeof( object ); // sizeof( 对象 );<br>2) sizeof( type_name ); // sizeof( 类型 );<br>3) sizeof object; // sizeof 对象;<br></div>
<p>所以，</p>
<div class="postCode"><font color="#0000ff">int</font>&nbsp;i;<br><font color="#0000ff">sizeof</font>(&nbsp;i&nbsp;);&nbsp;<font color="#008000">//&nbsp;ok</font><br><font color="#0000ff">sizeof</font>&nbsp;i;&nbsp;<font color="#008000">//&nbsp;ok</font><br><font color="#0000ff">sizeof</font>(&nbsp;<font color="#0000ff">int</font>&nbsp;);&nbsp;<font color="#008000">//&nbsp;ok</font><br><font color="#0000ff">sizeof</font>&nbsp;<font color="#0000ff">int</font>;&nbsp;<font color="#008000">//&nbsp;error</font> </div>
<p>既然写法3可以用写法1代替，为求形式统一以及减少我们大脑的负担，第3种写法，忘掉它吧！</p>
<p>实
际上，sizeof计算对象的大小也是转换成对对象类型的计算，也就是说，同种类型的不同对象其sizeof值都是一致的。这里，对象可以进一步延伸至表
达式，即sizeof可以对一个表达式求值，编译器根据表达式的最终结果类型来确定大小，一般不会对表达式进行计算。如： </p>
<div class="postCode"><font color="#0000ff">sizeof</font>(&nbsp;2&nbsp;);&nbsp;<font color="#008000">//&nbsp;2的类型为int，所以等价于&nbsp;sizeof(&nbsp;int&nbsp;);</font><br><font color="#0000ff">sizeof</font>(&nbsp;2&nbsp;+&nbsp;3.14&nbsp;);&nbsp;<font color="#008000">//&nbsp;3.14的类型为double，2也会被提升成double类型，所以等价于&nbsp;sizeof(&nbsp;double&nbsp;);</font> </div>
<p>sizeof也可以对一个函数调用求值，其结果是函数返回类型的大小，函数并不会被调用，我们来看一个完整的例子：</p>
<div class="postCode"><font color="#0000ff">char</font>&nbsp;foo()<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;printf(<font color="#ff00ff">"foo()&nbsp;has&nbsp;been&nbsp;called.\n"</font>);<br>&nbsp;&nbsp;&nbsp;&nbsp;<font color="#0000ff">return</font>&nbsp;'a';<br>}<br><font color="#0000ff">int</font>&nbsp;main()<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;size_t&nbsp;sz&nbsp;=&nbsp;<font color="#0000ff">sizeof</font>(&nbsp;foo()&nbsp;);&nbsp;<font color="#008000">//&nbsp;foo()&nbsp;的返回值类型为char，所以sz&nbsp;=&nbsp;sizeof(&nbsp;char&nbsp;)，foo()并不会被调用</font><br>&nbsp;&nbsp;&nbsp;&nbsp;printf(<font color="#ff00ff">"sizeof(&nbsp;foo()&nbsp;)&nbsp;=&nbsp;%d\n"</font>,&nbsp;sz);&nbsp;<br>} </div>
<p>C99标准规定，函数、不能确定类型的表达式以及位域（bit-field）成员不能被计算sizeof值，即下面这些写法都是错误的：</p>
<div class="postCode"><font color="#0000ff">sizeof</font>(&nbsp;foo&nbsp;);&nbsp;<font color="#008000">//&nbsp;error</font><br><br><font color="#0000ff">void</font>&nbsp;foo2()&nbsp;{&nbsp;}<br><font color="#0000ff">sizeof</font>(&nbsp;foo2()&nbsp;);&nbsp;<font color="#008000">//&nbsp;error</font><br><br><font color="#0000ff">struct</font>&nbsp;S<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;<font color="#0000ff">unsigned</font>&nbsp;<font color="#0000ff">int</font>&nbsp;f1&nbsp;:&nbsp;1;<br>&nbsp;&nbsp;&nbsp;&nbsp;<font color="#0000ff">unsigned</font>&nbsp;<font color="#0000ff">int</font>&nbsp;f2&nbsp;:&nbsp;5;<br>&nbsp;&nbsp;&nbsp;&nbsp;<font color="#0000ff">unsigned</font>&nbsp;<font color="#0000ff">int</font>&nbsp;f3&nbsp;:&nbsp;12;<br>};<br><font color="#0000ff">sizeof</font>(&nbsp;S.f1&nbsp;);&nbsp;<font color="#008000">//&nbsp;error</font> </div>
<p>3. sizeof的常量性</p>
<p>sizeof的计算发生在编译时刻，所以它可以被当作常量表达式使用，如：</p>
<div class="postCode"><font color="#0000ff">char</font>&nbsp;ary[&nbsp;<font color="#0000ff">sizeof</font>(&nbsp;<font color="#0000ff">int</font>&nbsp;)&nbsp;*&nbsp;10&nbsp;];&nbsp;<font color="#008000">//&nbsp;ok</font> </div>
<p>最新的C99标准规定sizeof也可以在运行时刻进行计算，如下面的程序在Dev-C++中可以正确执行： </p>
<div class="postCode"><font color="#0000ff">int</font>&nbsp;n;<br>n&nbsp;=&nbsp;10;&nbsp;<font color="#008000">//&nbsp;n动态赋值</font><br><font color="#0000ff">char</font>&nbsp;ary[n];&nbsp;<font color="#008000">//&nbsp;C99也支持数组的动态定义</font><br>printf(<font color="#ff00ff">"%d\n"</font>,&nbsp;<font color="#0000ff">sizeof</font>(ary));&nbsp;<font color="#008000">//&nbsp;ok.&nbsp;输出10</font> </div>
<p>但在没有完全实现C99标准的编译器中就行不通了，上面的代码在VC6中就通不过编译。所以我们最好还是认为sizeof是在编译期执行的，这样不会带来错误，让程序的可移植性强些。</p>
<p>4. 基本数据类型的sizeof</p>
<p>这里的基本数据类型指short、int、long、float、double这样的简单内置数据类型，由于它们都是和系统相关的，所以在不同的系统下取值可能不同，这务必引起我们的注意，尽量不要在这方面给自己程序的移植造成麻烦。</p>
<p>一般的，在32位编译环境中，sizeof(int)的取值为4。</p>
<p>5. 指针变量的sizeof</p>
<p>学
过数据结构的你应该知道指针是一个很重要的概念，它记录了另一个对象的地址。既然是来存放地址的，那么它当然等于计算机内部地址总线的宽度。所以在32位
计算机中，一个指针变量的返回值必定是4（注意结果是以字节为单位），可以预计，在将来的64位系统中指针变量的sizeof结果为8。</p>
<div class="postCode"><font color="#0000ff">char</font>*&nbsp;pc&nbsp;=&nbsp;<font color="#ff00ff">"abc"</font>;<br><font color="#0000ff">int</font>*&nbsp;pi;<br><font color="#0000ff">string</font>*&nbsp;ps;<br><font color="#0000ff">char</font>**&nbsp;ppc&nbsp;=&nbsp;&amp;pc;<br><font color="#0000ff">void</font>&nbsp;(*pf)();&nbsp;<font color="#008000">//&nbsp;函数指针</font><br><font color="#0000ff">sizeof</font>(&nbsp;pc&nbsp;);&nbsp;<font color="#008000">//&nbsp;结果为4</font><br><font color="#0000ff">sizeof</font>(&nbsp;pi&nbsp;);&nbsp;<font color="#008000">//&nbsp;结果为4</font><br><font color="#0000ff">sizeof</font>(&nbsp;ps&nbsp;);&nbsp;<font color="#008000">//&nbsp;结果为4</font><br><font color="#0000ff">sizeof</font>(&nbsp;ppc&nbsp;);&nbsp;<font color="#008000">//&nbsp;结果为4</font><br><font color="#0000ff">sizeof</font>(&nbsp;pf&nbsp;);&nbsp;<font color="#008000">//&nbsp;结果为4</font> </div>
<p>指针变量的sizeof值与指针所指的对象没有任何关系，正是由于所有的指针变量所占内存大小相等，所以MFC消息处理函数使用两个参数WPARAM、LPARAM就能传递各种复杂的消息结构（使用指向结构体的指针）。</p>
<p>6. 数组的sizeof</p>
<p>数组的sizeof值等于数组所占用的内存字节数，如：</p>
<div class="postCode"><font color="#0000ff">char</font>&nbsp;a1[]&nbsp;=&nbsp;<font color="#ff00ff">"abc"</font>;<br><font color="#0000ff">int</font>&nbsp;a2[3];<br><font color="#0000ff">sizeof</font>(&nbsp;a1&nbsp;);&nbsp;<font color="#008000">//&nbsp;结果为4，字符串末尾还存在一个NULL终止符</font><br><font color="#0000ff">sizeof</font>(&nbsp;a2&nbsp;);&nbsp;<font color="#008000">//&nbsp;结果为3*4=12（依赖于int）</font><br></div>
<p>一些朋友刚开始时把sizeof当作了求数组元素的个数，现在，你应该知道这是不对的，那么应该怎么求数组元素的个数呢？Easy，通常有下面两种写法：</p>
<div class="postCode"><font color="#0000ff">int</font>&nbsp;c1&nbsp;=&nbsp;<font color="#0000ff">sizeof</font>(&nbsp;a1&nbsp;)&nbsp;/&nbsp;<font color="#0000ff">sizeof</font>(&nbsp;<font color="#0000ff">char</font>&nbsp;);&nbsp;<font color="#008000">//&nbsp;总长度/单个元素的长度</font><br><font color="#0000ff">int</font>&nbsp;c2&nbsp;=&nbsp;<font color="#0000ff">sizeof</font>(&nbsp;a1&nbsp;)&nbsp;/&nbsp;<font color="#0000ff">sizeof</font>(&nbsp;a1[0]&nbsp;);&nbsp;<font color="#008000">//&nbsp;总长度/第一个元素的长度</font> </div>
<p>写到这里，提一问，下面的c3，c4值应该是多少呢？</p>
<div class="postCode"><font color="#0000ff">void</font>&nbsp;foo3(<font color="#0000ff">char</font>&nbsp;a3[3])<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;<font color="#0000ff">int</font>&nbsp;c3&nbsp;=&nbsp;<font color="#0000ff">sizeof</font>(&nbsp;a3&nbsp;);&nbsp;<font color="#008000">//&nbsp;c3&nbsp;==&nbsp;?</font><br>}<br><font color="#0000ff">void</font>&nbsp;foo4(<font color="#0000ff">char</font>&nbsp;a4[])<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;<font color="#0000ff">int</font>&nbsp;c4&nbsp;=&nbsp;<font color="#0000ff">sizeof</font>(&nbsp;a4&nbsp;);&nbsp;<font color="#008000">//&nbsp;c4&nbsp;==&nbsp;?</font><br>} </div>
<p>也
许当你试图回答c4的值时已经意识到c3答错了，是的，c3!=3。这里函数参数a3已不再是数组类型，而是蜕变成指针，相当于char*
a3，为什么？仔细想想就不难明白，我们调用函数foo1时，程序会在栈上分配一个大小为3的数组吗？不会！数组是&#8220;传址&#8221;的，调用者只需将实参的地址传
递过去，所以a3自然为指针类型（char*），c3的值也就为4。</p>
<p>7. 结构体的sizeof</p>
<p>这是初学者问得最多的一个问题，所以这里有必要多费点笔墨。让我们先看一个结构体：</p>
<div class="postCode"><font color="#0000ff">struct</font>&nbsp;S1<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;<font color="#0000ff">char</font>&nbsp;c;<br>&nbsp;&nbsp;&nbsp;&nbsp;<font color="#0000ff">int</font>&nbsp;i;<br>}; </div>
<p>问sizeof(s1)等于多少？聪明的你开始思考了，char占1个字节，int占4个字节，那么加起来就应该是5。是这样吗？你在你机器上试过了吗？也许你是对的，但很可能你是错的！VC6中按默认设置得到的结果为8。</p>
<p>Why？为什么受伤的总是我？ </p>
<p>请不要沮丧，我们来好好琢磨一下sizeof的定义——sizeof的结果等于对象或者类型所占的内存字节数，好吧，那就让我们来看看S1的内存分配情况：</p>
<div class="postCode">S1&nbsp;s1&nbsp;=&nbsp;{&nbsp;'a',&nbsp;0xFFFFFFFF&nbsp;}; </div>
<p>定义上面的变量后，加上断点，运行程序，观察s1所在的内存，你发现了什么？</p>
<p>以我的VC6.0为例，s1的地址为0x0012FF78，其数据内容如下：</p>
<div class="postCode">0012FF78: 61 CC CC CC FF FF FF FF<br></div>
<p>发现了什么？怎么中间夹杂了3个字节的CC？看看MSDN上的说明：</p>
<div class="postRefrence">When
applied to a structure type or variable, sizeof returns the actual
size, which may include padding bytes inserted for alignment.<br></div>
<p>原来如此，这就是传说中的字节对齐啊！一个重要的话题出现了。</p>
<p>为
什么需要字节对齐？计算机组成原理教导我们这样有助于加快计算机的取数速度，否则就得多花指令周期了。为此，编译器默认会对结构体进行处理（实际上其它地
方的数据变量也是如此），让宽度为2的基本数据类型（short等）都位于能被2整除的地址上，让宽度为4的基本数据类型（int等）都位于能被4整除的
地址上，以此类推。这样，两个数中间就可能需要加入填充字节，所以整个结构体的sizeof值就增长了。</p>
<p>让我们交换一下S1中char与int的位置：</p>
<div class="postCode"><font color="#0000ff">struct</font>&nbsp;S2<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;<font color="#0000ff">int</font>&nbsp;i;<br>&nbsp;&nbsp;&nbsp;&nbsp;<font color="#0000ff">char</font>&nbsp;c;<br>}; </div>
<p>看看sizeof(S2)的结果为多少，怎么还是8？再看看内存，原来成员c后面仍然有3个填充字节，这又是为什么啊？别着急，下面总结规律。</p>
<p>字节对齐的细节和编译器实现相关，但一般而言，满足三个准则：</p>
<div class="postConclusion">1) 结构体变量的首地址能够被其最宽基本类型成员的大小所整除；<br>2) 结构体每个成员相对于结构体首地址的偏移量（offset）都是成员大小的整数倍，如有需要编译器会在成员之间加上填充字节（internal adding）；<br>3) 结构体的总大小为结构体最宽基本类型成员大小的整数倍，如有需要编译器会在最末一个成员之后加上填充字节（trailing padding）。<br></div>
<p>对于上面的准则，有几点需要说明：</p>
<p>1) 前面不是说结构体成员的地址是其大小的整数倍，怎么又说到偏移量了呢？因为有了第1点存在，所以我们就可以只考虑成员的偏移量，这样思考起来简单。想想为什么。<br>结构体某个成员相对于结构体首地址的偏移量可以通过宏offsetof()来获得，这个宏也在stddef.h中定义，如下：</p>
<div class="postCode"><font color="#ff0000">#define</font>&nbsp;offsetof(s,m)&nbsp;(size_t)&amp;(((s&nbsp;*)0)-&gt;m) </div>
<p>例如，想要获得S2中c的偏移量，方法为</p>
<div class="postCode">size_t&nbsp;pos&nbsp;=&nbsp;offsetof(S2,&nbsp;c);&nbsp;<font color="#008000">//&nbsp;pos等于4</font> </div>
<p>2)
基本类型是指前面提到的像char、short、int、float、double这样的内置数据类型，这里所说的&#8220;数据宽度&#8221;就是指其sizeof的大
小。由于结构体的成员可以是复合类型，比如另外一个结构体，所以在寻找最宽基本类型成员时，应当包括复合类型成员的子成员，而不是把复合成员看成是一个整
体。但在确定复合类型成员的偏移位置时则是将复合类型作为整体看待。</p>
<p>这里叙述起来有点拗口，思考起来也有点挠头，还是让我们看看例子吧（具体数值仍以VC6为例，以后不再说明）：</p>
<div class="postCode"><font color="#0000ff">struct</font>&nbsp;S3<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;<font color="#0000ff">char</font>&nbsp;c1;<br>&nbsp;&nbsp;&nbsp;&nbsp;S1&nbsp;s;<br>&nbsp;&nbsp;&nbsp;&nbsp;<font color="#0000ff">char</font>&nbsp;c2<br>}; </div>
<p>S1的最宽基本成员的类型为int，S3在考虑最宽基本类型成员时是将S1&#8220;打散&#8221;看的，所以S3的最宽基本类型为int，这样，通过S3定义的变量，其存储空间首地址需要被4整除，整个sizeof(S3)的值也应该被4整除。</p>
<p>c1
的偏移量为0，s的偏移量呢？这时s是一个整体，它作为结构体变量也满足前面三个准则，所以其大小为8，偏移量为4，c1与s之间便需要3个填充字节，而
c2与s之间就不需要了，所以c2的偏移量为12，算上c2的大小为13，13是不能被4整除的，这样末尾还得补上3个填充字节。最后得到sizeof
(S3)的值为16。</p>
<p>通过上面的叙述，我们可以得到一个公式：</p>
<div class="postConclusion">结构体的大小等于最后一个成员的偏移量加上其大小再加上末尾的填充字节数目，即：<br>sizeof( struct ) = offsetof( last item ) + sizeof( last item ) + sizeof( trailing padding )</div>
<p>到
这里，朋友们应该对结构体的sizeof有了一个全新的认识，但不要高兴得太早，有一个影响sizeof的重要参量还未被提及，那便是编译器的pack指
令。它是用来调整结构体对齐方式的，不同编译器名称和用法略有不同，VC6中通过#pragma
pack实现，也可以直接修改/Zp编译开关。#pragma pack的基本用法为：#pragma pack( n
)，n为字节对齐数，其取值为1、2、4、8、16，默认是8，如果这个值比结构体成员的sizeof值小，那么该成员的偏移量应该以此值为准，即是说，
结构体成员的偏移量应该取二者的最小值，公式如下：</p>
<div class="postConclusion">offsetof( item ) = min( n, sizeof( item ) )<br></div>
<p>再看示例：</p>
<div class="postCode"><font color="#ff0000">#pragma</font>&nbsp;pack(<font color="#0000ff">push</font>)&nbsp;<font color="#008000">//&nbsp;将当前pack设置压栈保存</font><br><font color="#ff0000">#pragma</font>&nbsp;pack(2)&nbsp;<font color="#008000">//&nbsp;必须在结构体定义之前使用</font><br><font color="#0000ff">struct</font>&nbsp;S1<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;<font color="#0000ff">char</font>&nbsp;c;<br>&nbsp;&nbsp;&nbsp;&nbsp;<font color="#0000ff">int</font>&nbsp;i;<br>};<br><font color="#0000ff">struct</font>&nbsp;S3<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;<font color="#0000ff">char</font>&nbsp;c1;<br>&nbsp;&nbsp;&nbsp;&nbsp;S1&nbsp;s;<br>&nbsp;&nbsp;&nbsp;&nbsp;<font color="#0000ff">char</font>&nbsp;c2<br>};<br><font color="#ff0000">#pragma</font>&nbsp;pack(<font color="#0000ff">pop</font>)&nbsp;<font color="#008000">//&nbsp;恢复先前的pack设置</font> </div>
<p>计算sizeof(S1)时，min(2, sizeof(i))的值为2，所以i的偏移量为2，加上sizeof(i)等于6，能够被2整除，所以整个S1的大小为6。</p>
<p>同样，对于sizeof(S3)，s的偏移量为2，c2的偏移量为8，加上sizeof(c2)等于9，不能被2整除，添加一个填充字节，所以sizeof(S3)等于10。</p>
<p>现在，朋友们可以轻松的出一口气了，:)</p>
<p>还有一点要注意，&#8220;空结构体&#8221;（不含数据成员）的大小不为0，而是1。试想一个&#8220;不占空间&#8221;的变量如何被取地址、两个不同的&#8220;空结构体&#8221;变量又如何得以区分呢？于是，&#8220;空结构体&#8221;变量也得被存储，这样编译器也就只能为其分配一个字节的空间用于占位了。如下：</p>
<div class="postCode"><font color="#0000ff">struct</font>&nbsp;S5&nbsp;{&nbsp;};<br><font color="#0000ff">sizeof</font>(&nbsp;S5&nbsp;);&nbsp;<font color="#008000">//&nbsp;结果为1</font> </div>
<p>8. 含位域结构体的sizeof</p>
<p>前面已经说过，位域成员不能单独被取sizeof值，我们这里要讨论的是含有位域的结构体的sizeof，只是考虑到其特殊性而将其专门列了出来。</p>
<p>C99规定int、unsigned int和bool可以作为位域类型，但编译器几乎都对此作了扩展，允许其它类型类型的存在。</p>
<p>使用位域的主要目的是压缩存储，其大致规则为：</p>
<div class="postConclusion">1) 如果相邻位域字段的类型相同，且其位宽之和小于类型的sizeof大小，则后面的字段将紧邻前一个字段存储，直到不能容纳为止；<br>2) 如果相邻位域字段的类型相同，但其位宽之和大于类型的sizeof大小，则后面的字段将从新的存储单元开始，其偏移量为其类型大小的整数倍；<br>3) 如果相邻的位域字段的类型不同，则各编译器的具体实现有差异，VC6采取不压缩方式，Dev-C++采取压缩方式；<br>4) 如果位域字段之间穿插着非位域字段，则不进行压缩；<br>5) 整个结构体的总大小为最宽基本类型成员大小的整数倍。</div>
<p>还是让我们来看看例子。</p>
<p>示例1：</p>
<div class="postCode"><font color="#0000ff">struct</font>&nbsp;BF1<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;<font color="#0000ff">char</font>&nbsp;f1&nbsp;:&nbsp;3;<br>&nbsp;&nbsp;&nbsp;&nbsp;<font color="#0000ff">char</font>&nbsp;f2&nbsp;:&nbsp;4;<br>&nbsp;&nbsp;&nbsp;&nbsp;<font color="#0000ff">char</font>&nbsp;f3&nbsp;:&nbsp;5;<br>}; </div>
<p>其内存布局为：</p>
<pre class="postGraph">| f1  |  f2   | |  f3     |     |---------------------------------| | | | | | | | | | | | | | | | |---------------------------------0     3       7 8         13    16 (byte)</pre>
<p>位域类型为char，第1个字节仅能容纳下f1和f2，所以f2被压缩到第1个字节中，而f3只能从下一个字节开始。因此sizeof(BF1)的结果为2。</p>
示例2：<br>
<div class="postCode"><font color="#0000ff">struct</font>&nbsp;BF2<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;<font color="#0000ff">char</font>&nbsp;f1&nbsp;:&nbsp;3;<br>&nbsp;&nbsp;&nbsp;&nbsp;<font color="#0000ff">short</font>&nbsp;f2&nbsp;:&nbsp;4;<br>&nbsp;&nbsp;&nbsp;&nbsp;<font color="#0000ff">char</font>&nbsp;f3&nbsp;:&nbsp;5;<br>}; </div>
<p>由于相邻位域类型不同，在VC6中其sizeof为6，在Dev-C++中为2。</p>
示例3：<br>
<div class="postCode"><font color="#0000ff">struct</font>&nbsp;BF3<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;<font color="#0000ff">char</font>&nbsp;f1&nbsp;:&nbsp;3;<br>&nbsp;&nbsp;&nbsp;&nbsp;<font color="#0000ff">char</font>&nbsp;f2;<br>&nbsp;&nbsp;&nbsp;&nbsp;<font color="#0000ff">char</font>&nbsp;f3&nbsp;:&nbsp;5;<br>}; </div>
<p>非位域字段穿插在其中，不会产生压缩，在VC6和Dev-C++中得到的大小均为3。</p>
<p>9. 联合体的sizeof</p>
<p>结构体在内存组织上是顺序式的，联合体则是重叠式，各成员共享一段内存，所以整个联合体的sizeof也就是每个成员sizeof的最大值。结构体的成员也可以是复合类型，这里，复合类型成员是被作为整体考虑的。</p>
<p>所以，下面例子中，U的sizeof值等于sizeof(s)。</p>
<div class="postCode"><font color="#0000ff">union</font>&nbsp;U<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;<font color="#0000ff">int</font>&nbsp;i;<br>&nbsp;&nbsp;&nbsp;&nbsp;<font color="#0000ff">char</font>&nbsp;c;<br>&nbsp;&nbsp;&nbsp;&nbsp;S1&nbsp;s;<br>}; </div>
</div>
<br><img src ="http://www.cppblog.com/paladino/aggbug/26578.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/paladino/" target="_blank">Gu.paladino</a> 2007-06-18 18:26 <a href="http://www.cppblog.com/paladino/articles/26578.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>学C++时要注意的</title><link>http://www.cppblog.com/paladino/articles/26181.html</link><dc:creator>Gu.paladino</dc:creator><author>Gu.paladino</author><pubDate>Tue, 12 Jun 2007 09:13:00 GMT</pubDate><guid>http://www.cppblog.com/paladino/articles/26181.html</guid><wfw:comment>http://www.cppblog.com/paladino/comments/26181.html</wfw:comment><comments>http://www.cppblog.com/paladino/articles/26181.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/paladino/comments/commentRss/26181.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/paladino/services/trackbacks/26181.html</trackback:ping><description><![CDATA[这个写的一定是过来的人啊，不收藏对不起自己！<br><br>1.把C++当成一门新的语言学习（和C没啥关系！真的。）；<br>2.看《Thinking In C++》，不要看《C++变成死相》；<br>3.看《The C++ Programming Language》和《Inside The C++ Object Model》,不要因为他们很难而我们自己是初学者所以就不看；<br>4.不要被VC、BCB、BC、MC、TC等词汇所迷惑——他们都是集成开发环境，而我们要学的是一门语言；<br>5.不要放过任何一个看上去很简单的小编程问题——他们往往并不那么简单，或者可以引伸出很多知识点；<br>6.会用Visual C++，并不说明你会C++；<br>7.学class并不难，template、STL、generic programming也不过如此——难的是长期坚持实践和不遗余力的博览群书；<br>8.如果不是天才的话，想学编程就不要想玩游戏——你以为你做到了，其实你的C++水平并没有和你通关的能力一起变高——其实可以时刻记住：学C++是为了编游戏的；<br>9.看Visual C++的书，是学不了C++语言的；<br>10.浮躁的人容易说：XX语言不行了，应该学YY；——是你自己不行了吧！？<br>11.浮躁的人容易问：我到底该学什么；——别问，学就对了；<br>12.浮躁的人容易问：XX有钱途吗；——建议你去抢银行；<br>13.浮躁的人容易说：我要中文版！我英文不行！——不行？学呀！<br>14.浮躁的人容易问：XX和YY哪个好；——告诉你吧，都好——只要你学就行；<br>15.浮躁的人分两种：a)只观望而不学的人；b)只学而不坚持的人；<br>16.把时髦的技术挂在嘴边，还不如把过时的技术记在心里；<br>17.C++不仅仅是支持面向对象的程序设计语言；<br>18.学习编程最好的方法之一就是阅读源代码；<br>19.在任何时刻都不要认为自己手中的书已经足够了；<br>20.请阅读《The Standard C++ Bible》(中文版：标准C++宝典)，掌握C++标准；<br>21.看得懂的书，请仔细看；看不懂的书，请硬着头皮看；<br>22.别指望看第一遍书就能记住和掌握什么——请看第二遍、第三遍；<br>23.请看《Effective C++》和《More Effective C++》以及《Exceptional C++》；<br>24.不要停留在集成开发环境的摇篮上，要学会控制集成开发环境，还要学会用命令行方式处理程序；<br>25.和别人一起讨论有意义的C++知识点，而不是争吵XX行不行或者YY与ZZ哪个好；<br>26.请看《程序设计实践》，并严格的按照其要求去做；<br>27.不要因为C和C++中有一些语法和关键字看上去相同，就认为它们的意义和作用完全一样；<br>28.C++绝不是所谓的C的&#8220;扩充&#8221;——如果C++一开始就起名叫Z语言，你一定不会把C和Z语言联系得那么紧密；<br>29.请不要认为学过XX语言再改学C++会有什么问题——你只不过又在学一门全新的语言而已；<br>30.读完了《Inside The C++ Object Model》以后再来认定自己是不是已经学会了C++；<br>31.学习编程的秘诀是：编程，编程，再编程；<br>32.请留意下列书籍：《C++面向对象高效编程（C++ Effective Object-Oriented Software Construction）》《面向对象软件构造(Object-Oriented Software Construction)》《设计模式（Design Patterns）》《The Art of Computer Programming》；<br>33.记住：面向对象技术不只是C++专有的；<br>34.请把书上的程序例子亲手输入到电脑上实践，即使配套光盘中有源代码；<br>35.把在书中看到的有意义的例子扩充；<br>36.请重视C++中的异常处理技术，并将其切实的运用到自己的程序中；<br>37.经常回顾自己以前写过的程序，并尝试重写，把自己学到的新知识运用进去；<br>38.不要漏掉书中任何一个练习题——请全部做完并记录下解题思路；<br>39.C++语言和C++的集成开发环境要同时学习和掌握；<br>40.既然决定了学C++,就请坚持学下去，因为学习程序设计语言的目的是掌握程序设计技术，而程序设计技术是跨语言的；<br>41.就让C++语言的各种平台和开发环境去激烈的竞争吧，我们要以学习C++语言本身为主；<br>42.当你写C++程序写到一半却发现自己用的方法很拙劣时，请不要马上停手；请尽快将余下的部分粗略的完成以保证这个设计的完整性，然后分析自己的错误并重新设计和编写（参见43）；<br>43.别心急，设计C++的class确实不容易；自己程序中的class和自己的class设计水平是在不断的编程实践中完善和发展的；<br>44.决不要因为程序&#8220;很小&#8221;就不遵循某些你不熟练的规则——好习惯是培养出来的，而不是一次记住的；<br>45.每学到一个C++难点的时候，尝试着对别人讲解这个知识点并让他理解——你能讲清楚才说明你真的理解了；<br>46.记录下在和别人交流时发现的自己忽视或不理解的知识点；<br>47.请不断的对自己写的程序提出更高的要求,哪怕你的程序版本号会变成Version 100.XX；<br>48.保存好你写过的所有的程序——那是你最好的积累之一；<br>49.请不要做浮躁的人；<br>50.请热爱C++! <br><img src ="http://www.cppblog.com/paladino/aggbug/26181.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/paladino/" target="_blank">Gu.paladino</a> 2007-06-12 17:13 <a href="http://www.cppblog.com/paladino/articles/26181.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C++资源导引</title><link>http://www.cppblog.com/paladino/articles/25664.html</link><dc:creator>Gu.paladino</dc:creator><author>Gu.paladino</author><pubDate>Wed, 06 Jun 2007 08:44:00 GMT</pubDate><guid>http://www.cppblog.com/paladino/articles/25664.html</guid><description><![CDATA[<span style="font-weight: bold; font-size: 18pt;">这文章太强了，我一定要收藏，对不起自己！</span><br><br>--------------------------------------------------------------------------------<br><br>　　1，前言<br><br>　　无数次听到&#8220;我要开始学习C++!&#8221;的呐喊，无数次听到&#8220;C++太复杂了，我真的<br>学不会&#8221;的无奈。Stan Lippman先生曾在《C++ Primer》一书中指出&#8220;C++是最为难<br>学的高级程序设计语言之一&#8221;，人们常将&#8220;之一&#8221;去掉以表达自己对C++的敬畏。诚<br>然，C++程序设计语言对于学习者的确有很多难以逾越的鸿沟，体系结构的庞大，应<br>接不暇并不断扩充的特性&#8230;&#8230;除此之外，参考资料之多与冗杂使它的学习者望而却<br>步，欲求深入者苦不堪言。希望这一份不完全导引能够成为您C++学习之路上的引路<br>灯。<br><br>　　撰写本文的初衷并不打算带领大家体验古老的C++历史，如果你想了解C++的历<br>史与其前期发展中诸多技术的演变，你应当去参考Bjarne的《The Design and Evo<br>lution of C++》。当然也不打算给大家一个无所不包的宝典（并非不想：其一是因<br>水平有限，其二无奈C++之博大精深），所给出的仅仅是一些我们认为对于想学习C<br>++的广大读者来说最重要并且触手可及的开发与学习资源。<br><br>　　本文介绍并分析了一些编译器，开发环境，库，少量的书籍以及参考网站，并<br>且尽可能尝试着给出一个利用这些资源的导引，望对如同我们一样的初学者能够有<br>所裨益。<br><br>------------------------------------------------------------------------<br>--------<br><br>　　2，编译器<br><br>　　在C++之外的任何语言中，编译器都从来没有受到过如此之重视。因为C++是一<br>门相当复杂的语言，所以编译器也难于构建。直到最近我们才开始能够使用上完全<br>符合C++标准的编译器（哦，你可能会责怪那些编译器厂商不能尽早的提供符合标准<br>的编译器，这只能怪他们各自维系着自身的一套别人不愿接受的标准）。什么？你<br>说这无关紧要？哦，不，你所需要的是和标准化C++高度兼容的编译环境。长远来看<br>，只有这样的编译器对C++开发人员来说才是最有意义的工具，尤其是对于程序设计<br>语言的学习者。一至性让代码具备可移植性，并让一门语言及其库的应用更为广泛<br>。嗯，是的，我们这里只打算介绍一些公认的优秀编译器。<br><br>　　2.1 Borland C++<br><br>　　这个是Borland C++ Builder和Borland C++ Builder X这两种开发环境的后台<br>编译器。（哦，我之所以将之分为两种开发环境你应当能明白为什么，正如Delphi<br>7到Delphi8的转变，是革命性的两代。）Borland C++由老牌开发工具厂商Borland<br>倾力打造。该公司的编译器素以速度快，空间效率高著称，Borland C++ 系列编译<br>器秉承了这个传统，属于非常优质的编译器。标准化方面早在5.5版本的编译器中对<br>标准化C++的兼容就达到了92.73%。目前最新版本是Borland C++ Builder X中的6.<br>0版本，官方称100%符合ANSI/ISO的C++标准以及C99标准。嗯&#8230;这正是我前面所指的<br>&#8220;完全符合C++标准的编译器&#8221;。<br><br>　　2.2 Visual C++<br><br>　　这个正是我们熟知的Visual Studio 和 Visual Studio.net 2002, 2003以及2<br>005 Whidbey中带的C++编译器。由Microsoft公司研制。在Visual Studio 6.0中，<br>因为编译器有太多地方不能与后来出现的C++标准相吻合而饱受批评（想想你在使用<br>STL的时候编译时报出的那些令人厌恶的error和warning吧）。VC++6.0对标准化C+<br>+的兼容只有83.43%。但是随着C++编译器设计大师Stanley Lippman以及诸多C++社<br>群达人的加盟，在Visual Studio.NET 2003中，Visual C++编译器已经成为一个非<br>常成熟可靠的C++编译器了。Dr.Dobb's Journal的评测显示Visual C++7.1对标准C<br>++的兼容性高达98.22%，一度成为CBX之前兼容性最好的编译器。结合强大的Visua<br>l Studio.NET开发环境，是一个非常不错的选择。至于Whidbey时代的Visual C++,<br>似乎微软所最关注的是C++/CLI&#8230;&#8230;我们不想评论微软下一代的C++编译器对标准化<br>兼容如何，但他确实越来越适合.NET (其实你和我的感觉可能是一样的，微软不应<br>当把标准C++这块肥肉丢给Borland,然而微软可能并不这样认为)。<br><br>　　2.3 GNU C++<br><br>　　著名的开源C++编译器。是类Unix操作系统下编写C++程序的首选。特点是有非<br>常好的移植性，你可以在非常广泛的平台上使用它，同时也是编写跨平台，嵌入式<br>程序很好的选择。另外在符合标准这个方面一直都非常好，GCC3.3大概能够达到96<br>.15%。但是由于其跨平台的特性，在代码尺寸速度等优化上略微差一点。<br><br>　　基于GNU C++的编译器有很多，比如：<br><br>　　(1) Mingw<br><br>　　http://www.mingw.org/<br><br>　　GCC的一个Windows的移植版本（Dev-C++的后台）<br><br>　　(2) Cygwin<br><br>　　http://sources.redhat.com/cygwin/<br><br>　　GCC的另外一个Windows移植版本是Cygwin的一部分，Cygwin是Windows下的一个<br>Unix仿真环境。严格的说是模拟GNU的环境，这也就是"Gnu's Not Unix"要表达的意<br>思，噢，扯远了，这并不是我们在这里关心的实质内容。<br><br>　　(3) Djgpp<br><br>　　http://www.delorie.com/djgpp/<br><br>　　这是GCC的DOS移植版本。<br><br>　　(4) RSXNT<br><br>　　http://www.mathematik.uni-bielefeld.de/~rainer/<br><br>　　这是GCC的DOS和Windows移植版本。<br><br>　　(5) Intel C++<br><br>　　著名CPU制造厂商Intel出品的编译器，Special Design for Intel x86！对于<br>Intel x86结构的CPU经过特别的优化。在有些应用情况下，特别是数值计算等高性<br>能应用，仅仅采用Intel的编译器编译就能大幅度的提高性能。<br><br>　　(6) Digital Mars C++<br><br>　　网络上提供免费下载，Zortech/Symantec C++的继承者，其前身在当年惨烈的<br>C++四国战中也是主角之一。<br><br>------------------------------------------------------------------------<br>--------<br><br>　　3，开发环境<br><br>　　开发环境对于程序员的作用不言而喻。选择自己朝夕相处的环境也不是容易的<br>事情，特别是在IDE如此丰富的情况下。下面就是我们推荐的一些常见的C++开发环<br>境，并没有包括一些小型的，罕见的IDE。其中任何一款都是功能丰富，可以用作日<br>常开发使用的。对于不同层面的开发者，请参见内文关于适用对象的描述。<br><br>　　3.1 Visual Studio 6.0<br><br>　　这个虽然是Microsoft公司的老版本的开发环境，但是鉴于其后继版本Visual<br>Studio.NET的庞大身躯，以及初学者并不那么高的功能要求，所以推荐这个开发环<br>境给C++的初学者，供其学习C++的最基本的部分，比如C的那部分子集，当然你别指<br>望他能够支持最新的C99标准。在日常的开发中，仍然有很多公司使用这个经典稳定<br>的环境，比如笔者就看曾亲见有些公司将其编译器替换为GCC做手机开发之用。<br><br>　　3.2 Visual Studio.NET 2003<br><br>　　作为Microsoft公司官方正式发布的最新版本开发环境，其中有太多激动人心的<br>功能。结合其最新的C++编译器。对于机器配置比较好的开发人员来说，使用这个开<br>发环境将能满足其大部分的要求。这里不打算单独说Visual Studio Whidbey,虽然<br>Visual Studio .NET 2005 - Whidbey社区预览版已经推出，但暂不是很稳定，读者<br>可以亲身去体验。<br><br>　　3.3 Borland C++ Builder 6<br><br>　　这个并不是Borland的C++开发环境的最新版本。选择它的原因是它不是用Java<br>写的IDE，速度比较快。它有一个很完善的GUI窗体设计器，和Delphi共用一个VCL。<br>由于这些特点，比较适合初学者上手。但是由于其GUI的中心位置，可能不利于对于<br>C++语言的学习。而且其为了支持VCL这个Object Pascal写的库也对C++进行了一些<br>私有的扩充。使得人们有一个不得不接受的事实：&#8220;Borland C++ Builder 6的高手<br>几乎都是Delphi高手&#8221;。<br><br>　　3.4 Borland C++ Builder X<br><br>　　正如前文所述，虽然版本号上和前面那个IDE非常相象，但是其实它们是完全不<br>同的两个集成开发环境。C++Builder更多的是一个和Delphi同步的C++版本的开发环<br>境，C++BuilderX则是完全从C++的角度思考得出的一个功能丰富的IDE。其最大的特<br>点是跨平台，跨编译器，多种Framework的集成，并且有一个WxWindows为基础的GU<br>I设计器。尤其是采用了纯C++来重写了整个Framework,摒弃了以前令人无奈的版本<br>。对于C++的开发来说，从编译器，到库，到功能集成都是非常理想的。可以预见，<br>Borland C++ Builder X 2.0很值得C++爱好者期待。唯一令人难堪之处是作为一个<br>C++的开发工具，其IDE是用Java写的，在配置不够理想的机器上请慎重考虑再安装<br>。<br><br>　　3.5 Emacs + GCC<br><br>　　前面讲的大部分是Windows环境下的集成开发环境。Linux上的开发者更倾向于<br>使用Emacs来编辑C++的文件，用Makefile来命令GCC做编译。虽然看上去比较松散，<br>但是这些东西综合起来还是一个开0发环境。如果你能够娴熟的使用这样的环境写程<br>序，你的水平应该足够指导我们来写这篇陋文了。<br><br>　　3.6 Dev C++<br><br>　　GCC是一个很好的编译器。在Windows上的C++编译器一直和标准有着一段距离的<br>时候，GCC就是一个让Windows下开发者流口水的编译器。Dev-C++就是能够让GCC跑<br>在Windows下的工具，作为集成开发环境，还提供了同专业IDE相媲美的语法高亮，<br>代码提示，调试等功能。由于使用Delphi开发，占用内存少，速度很快，比较适合<br>轻量级的学习和使用。<br><br>　　3.7 Eclipse + CDT<br><br>　　Eclipse可是近来大名鼎鼎的开发工具。最新一期的Jolt大奖就颁给了这个杰出<br>的神物。说其神奇是因为，它本身是用Java写的，但是拥有比一般Java写的程序快<br>得多的速度。而且因为其基于插件组装一切的原则，使得能够有CDT这样的插件把E<br>clipse变成一个C/C++的开发环境。如果你一直用Eclipse写Java的程序，不妨用它<br>体验一下C++开发的乐趣。<br><br>------------------------------------------------------------------------<br>--------<br><br>　　4，工具<br><br>　　C++的辅助工具繁多，我们分门别类的为大家作介绍：<br><br>　　4.1 文档类<br><br>　　(1) Doxygen<br><br>　　参考站点：http://www.doxygen.org<br><br>　　Doxygen是一种适合C风格语言（如C++、C、IDL、Java甚至包括C#和PHP）的、<br>开放源码的、基于命令行的文档产生器。<br><br>　　(2) C++2HTML<br><br>　　参考站点：http://www.bedaux.net/cpp2html/<br><br>　　把C++代码变成语法高亮的HTML<br><br>　　(3) CodeColorizer<br><br>　　参考站点：http://www.chami.com/colorizer/<br><br>　　它能把好几种语言的源代码着色为HTML<br><br>　　(4) Doc-O-Matic<br><br>　　参考站点：http://www.doc-o-matic.com/<br><br>　　Doc-O_Matic为你的C/C++，C++.net，Delphi/Pascal, VB.NET，C#和Java程序<br>或者组件产生准确的文档。Doc-O-Matic使用源代码中的符号和注释以及外部的文档<br>文件创建与流行的文档样式一致的文档。<br><br>　　(5) DocVizor<br><br>　　参考站点：http://www.ucancode.net/Products/DocBuilder/Features.htm<br><br>　　DocVizor满足了面向对象软件开发者的基本要求——它让我们能够看到C++工程<br>中的类层次结构。DocVizor快速地产生完整可供打印的类层次结构图，包括从第三<br>方库中来的那些类，除此之外DocVizor还能从类信息中产生HTML文件。<br><br>　　(6) SourcePublisher C++<br><br>　　参考站点：http://www.scitools.com/sourcepublisher_c.html<br><br>　　给源代码产生提供快速直观的HTML报表，包括代码，类层次结构，调用和被调<br>用树，包含和被包含树。支持多种操作系统。<br><br>　　(7) Understand<br><br>　　参考站点：http://www.scitools.com/ucpp.html<br><br>　　分析任何规模的C或者C++工程，帮助我们更好的理解以及编写文档。<br><br>　　4.2 代码类<br><br>　　(1) CC-Rider<br><br>　　参考站点：http://www.cc-rider.com<br><br>　　CC-Rider是用于C/C++程序强大的代码可视化工具，通过交互式浏览、编辑及自<br>动文件来促进程序的维持和发展。<br><br>　　(2) CodeInspect<br><br>　　参考站点：http://www.yokasoft.com/<br><br>　　一种新的C/C++代码分析工具。它检查我们的源代码找出非标准的，可能的，以<br>及普通的错误代码。<br><br>　　(3) CodeWizard<br><br>　　参考站点：http://www.parasoft.com<br><br>　　先进的C/C++源代码分析工具，使用超过500个编码规范自动化地标明危险的，<br>但是编译器不能检查到的代码结构。<br><br>　　(4) C++ Validation Test Suites<br><br>　　参考站点：http://www.plumhall.com/suites.html<br><br>　　一组用于测试编译器和库对于标准吻合程度的代码库。<br><br>　　(5) CppRefactory<br><br>　　参考站点：http://cpptool.sourceforge.net/<br><br>　　CPPRefactory是一个使得开发者能够重构他们的C++代码的程序。目的是使得C<br>++代码的重构能够尽可能的有效率和简单。<br><br>　　(6) Lzz<br><br>　　参考站点：http://www.lazycplusplus.com/<br><br>　　Lzz是一个自动化许多C++编程中的体力活的工具。它能够节省我们许多事件并<br>且使得编码更加有乐趣。给出一系列的声明，Lzz会给我们创建头文件和源文件。<br><br>　　(7) QA C++ Generation 2000<br><br>　　参考站点：http://www.programmingresearch.com/solutions/qacpp.htm<br><br>　　它关注面向对象的C++源代码，对有关于设计，效率，可靠性，可维护性的部分<br>提出警告信息。<br><br>　　(8) s-mail project - Java to C++DOL<br><br>　　参考站点：http://sadlocha.strefa.pl/s-mail/ja2dol.html<br><br>　　把Java源代码翻译为相应的C++源代码的命令行工具。<br><br>　　(9) SNIP from Cleanscape Software International<br><br>　　参考站点：http://www.cleanscape.net/stdprod/snip/index.html<br><br>　　一个填平编码和设计之间沟壑的易于使用的C++开发工具，节省大量编辑和调试<br>的事件，它还使得开发者能够指定设计模式作为对象模型，自动从对象模型中产生<br>C++的类。<br><br>　　(10) SourceStyler C++<br><br>　　参考站点：http://www.ochresoftware.com/<br><br>　　对C/C++源代码提供完整的格式化和排版控制的工具。提供多于75个的格式化选<br>项以及完全支持ANSI C++。<br><br>　　4.3 编译类<br><br>　　(1) Compilercache<br><br>　　参考站点：http://www.erikyyy.de/compilercache/<br><br>　　Compilercache是一个对你的C和C++编译器的封装脚本。每次我们进行编译，封<br>装脚本，把编译的结果放入缓存，一旦编译相同的东西，结果将从缓存中取出而不<br>是再次编译。<br><br>　　(2) Ccache<br><br>　　参考站点：http://ccache.samba.org/<br><br>　　Ccache是一个编译器缓存。它使用起来就像C/C++编译器的缓存预处理器，编译<br>速度通常能提高普通编译过程的5~10倍。<br><br>　　(3) Cmm (C++ with MultiMethods)<br><br>　　参考站点：http://www.op59.net/cmm/cmm-0.28/users.html<br><br>　　这是一种C++语言的扩展。读入Cmm源代码输出C++的源代码，功能是对C++语言<br>添加了对multimethod的支持。<br><br>　　(4) The Frost Project<br><br>　　参考站点：http://frost.flewid.de/<br><br>　　Forst使得你能够在C++程序中像原生的C++特性一样使用multimethod以及虚函<br>数参数。它是一个编译器的外壳。<br><br>　　4.4 测试和调试类<br><br>　　(1) CPPUnit<br><br>　　CppUnit 是个基于 LGPL 的开源项目，最初版本移植自 JUnit，是一个非常优<br>秀的开源测试框架。CppUnit 和 JUnit 一样主要思想来源于极限编程。主要功能就<br>是对单元测试进行管理，并可进行自动化测试。<br><br>　　(2) C++Test<br><br>　　参考站点：http://www.parasoft.com/<br><br>　　C++ Test是一个单元测试工具，它自动化了C和C++类，函数或者组件的测试。<br><br><br>　　(3) Cantata++<br><br>　　参考站点：http://www.iplbath.com/products/tools/pt400.shtml<br><br>　　设计的目的是为了满足在合理的经济开销下使用这个工具可以让开发工程师开<br>展单元测试和集成测试的需求.<br><br>　　(4) Purify<br><br>　　参考站点：http://www-900.ibm.com/cn/software/rational/products/purif<br>yplus/index.shtml<br><br>　　IBM Rational PurifyPlus是一套完整的运行时分析工具，旨在提高应用程序的<br>可靠性和性能。PurifyPlus将内存错误和泄漏检测、应用程序性能描述、代码覆盖<br>分析等功能组合在一个单一、完整的工具包中。<br><br>　　(5) BoundsChecker<br><br>　　BoundsChecker是一个C++运行时错误检测和调试工具。它通过在Visual Studi<br>o内自动化调试过程加速开发并且缩短上市的周期。BoundsChecker提供清楚，详细<br>的程序错误分析，许多是对C++独有的并且在static，stack和heap内存中检测和诊<br>断错误，以及发现内存和资源的泄漏。　　(6) Insure++<br><br>　　参考站点：http://www.parasoft.com/<br><br>　　一个自动化的运行时程序测试工具，检查难以察觉的错误,如内存覆盖，内存泄<br>漏，内存分配错误，变量初始化错误，变量定义冲突，指针错误，库错误，逻辑错<br>误和算法错误等。<br><br>　　(7) GlowCode<br><br>　　参考站点：http://www.glowcode.com/<br><br>　　GlowCode包括内存泄漏检查，code profiler，函数调用跟踪等功能。给C++开<br>发者提供完整的错误诊断，和运行时性能分析工具包。<br><br>　　(8) Stack Spy<br><br>　　参考站点：http://www.imperioustech.com/<br><br>　　它能捕捉stack corruption, stack over run, stack overflow等有关栈的错<br>误。<br><br>------------------------------------------------------------------------<br>--------<br><br>　　5，库<br><br>　　在C++中，库的地位是非常高的。C++之父 Bjarne Stroustrup先生多次表示了<br>设计库来扩充功能要好过设计更多的语法的言论。现实中，C++的库门类繁多，解决<br>的问题也是极其广泛，库从轻量级到重量级的都有。不少都是让人眼界大开，亦或<br>是望而生叹的思维杰作。由于库的数量非常庞大，而且限于笔者水平，其中很多并<br>不了解。所以文中所提的一些库都是比较著名的大型库。<br><br>　　5.1 标准库<br><br>　　标准库中提供了C++程序的基本设施。虽然C++标准库随着C++标准折腾了许多年<br>，直到标准的出台才正式定型，但是在标准库的实现上却很令人欣慰得看到多种实<br>现，并且已被实践证明为有工业级别强度的佳作。<br><br>　　(1) Dinkumware C++ Library<br><br>　　参考站点：http://www.dinkumware.com/<br><br>　　P.J. Plauger编写的高品质的标准库。P.J. Plauger博士是Dr. Dobb's程序设<br>计杰出奖的获得者。其编写的库长期被Microsoft采用，并且最近Borland也取得了<br>其OEM的license，在其C/C++的产品中采用Dinkumware的库。<br><br>　　(2) RogueWave Standard C++ Library<br><br>　　参考站点：http://www.roguewave.com/<br><br>　　这个库在Borland C++ Builder的早期版本中曾经被采用，后来被其他的库给替<br>换了。笔者不推荐使用。<br><br>　　(3) SGI STL<br><br>　　参考站点：http://www.roguewave.com/<br><br>　　SGI公司的C++标准模版库。<br><br>　　(4) STLport<br><br>　　参考站点：http://www.stlport.org/<br><br>　　SGI STL库的跨平台可移植版本。<br><br>　　5.2 &#8220;准&#8221;标准库 - Boost<br><br>　　参考站点：http://www.boost.org<br><br>　　国内镜像：http://www.c-view.org/tech/lib/boost/index.htm<br><br>　　Boost库是一个经过千锤百炼、可移植、提供源代码的C++库，作为标准库的后<br>备，是C++标准化进程的发动机之一。 Boost库由C++标准委员会库工作组成员发起<br>，在C++社区中影响甚大，其成员已近2000人。 Boost库为我们带来了最新、最酷、<br>最实用的技术，是不折不扣的&#8220;准&#8221;标准库。<br><br>　　Boost中比较有名气的有这么几个库：<br><br>　　Regex<br><br>　　正则表达式库<br><br>　　Spirit<br><br>　　LL parser framework，用C++代码直接表达EBNF<br><br>　　Graph<br><br>　　图组件和算法<br><br>　　Lambda<br><br>　　在调用的地方定义短小匿名的函数对象，很实用的functional功能<br><br>　　concept check<br><br>　　检查泛型编程中的concept<br><br>&nbsp;<br><br>　　Mpl<br><br>　　用模板实现的元编程框架<br><br>&nbsp;<br><br>　　Thread<br><br>　　可移植的C++多线程库<br><br>&nbsp;<br><br>　　Python<br><br>　　把C++类和函数映射到Python之中<br><br>　　Pool<br><br>　　内存池管理<br><br>&nbsp;<br><br>　　smart_ptr<br><br>　　5个智能指针，学习智能指针必读，一份不错的参考是来自CUJ的文章：<br><br>　　Smart Pointers in Boost，哦，这篇文章可以查到，CUJ是提供在线浏览的。<br>中文版见笔者在《Dr. Dobb's Journal软件研发杂志》第7辑上的译文。<br><br>　　Boost总体来说是实用价值很高，质量很高的库。并且由于其对跨平台的强调，<br>对标准C++的强调，是编写平台无关，现代C++的开发者必备的工具。但是Boost中也<br>有很多是实验性质的东西，在实际的开发中实用需要谨慎。并且很多Boost中的库功<br>能堪称对语言功能的扩展，其构造用尽精巧的手法，不要贸然的花费时间研读。Bo<br>ost另外一面，比如Graph这样的库则是具有工业强度，结构良好，非常值得研读的<br>精品代码，并且也可以放心的在产品代码中多多利用。<br><br>　　5.3 GUI<br><br>　　在众多C++的库中，GUI部分的库算是比较繁荣，也比较引人注目的。在实际开<br>发中，GUI库的选择也是非常重要的一件事情，下面我们综述一下可选择的GUI库，<br>各自的特点以及相关工具的支持。<br><br>　　(1) MFC<br><br>　　大名鼎鼎的微软基础类库（Microsoft Foundation Class）。大凡学过VC++的<br>人都应该知道这个库。虽然从技术角度讲，MFC是不大漂亮的，但是它构建于Windo<br>ws API 之上，能够使程序员的工作更容易,编程效率高，减少了大量在建立 Windo<br>ws 程序时必须编写的代码，同时它还提供了所有一般 C++ 编程的优点，例如继承<br>和封装。MFC 编写的程序在各个版本的Windows操作系统上是可移植的，例如，在<br>Windows 3.1下编写的代码可以很容易地移植到 Windows NT 或 Windows 95 上。但<br>是在最近发展以及官方支持上日渐势微。<br><br>　　(2) QT<br><br>　　参考网站：http://www.trolltech.com/<br><br>　　Qt是Trolltech公司的一个多平台的C++图形用户界面应用程序框架。它提供给<br>应用程序开发者建立艺术级的图形用户界面所需的所用功能。Qt是完全面向对象的<br>很容易扩展，并且允许真正地组件编程。自从1996年早些时候，Qt进入商业领域，<br>它已经成为全世界范围内数千种成功的应用程序的基础。Qt也是流行的Linux桌面环<br>境KDE 的基础，同时它还支持Windows、Macintosh、Unix/X11等多种平台。<br><br>　　(3) WxWindows<br><br>　　参考网站：http://www.wxwindows.org/<br><br>　　跨平台的GUI库。因为其类层次极像MFC，所以有文章介绍从MFC到WxWindows的<br>代码移植以实现跨平台的功能。通过多年的开发也是一个日趋完善的GUI库，支持同<br>样不弱于前面两个库。并且是完全开放源代码的。新近的C++ Builder X的GUI设计<br>器就是基于这个库的。<br><br>　　(4) Fox<br><br>　　参考网站：http://www.fox-toolkit.org/<br><br>　　开放源代码的GUI库。作者从自己亲身的开发经验中得出了一个理想的GUI库应<br>该是什么样子的感受出发，从而开始了对这个库的开发。有兴趣的可以尝试一下。<br><br><br>　　(5) WTL<br><br>　　基于ATL的一个库。因为使用了大量ATL的轻量级手法，模板等技术，在代码尺<br>寸，以及速度优化方面做得非常到位。主要面向的使用群体是开发COM轻量级供网络<br>下载的可视化控件的开发者。<br><br>　　(6) GTK<br><br>　　参考网站：http://gtkmm.sourceforge.net/<br><br>　　GTK是一个大名鼎鼎的C的开源GUI库。在Linux世界中有Gnome这样的杀手应用。<br>而GTK就是这个库的C++封装版本。<br><br>　　5.4 网络通信<br><br>　　(1) ACE<br><br>　　参考网站：http://www.cs.wustl.edu/~schmidt/ACE.html<br><br>　　C++库的代表，超重量级的网络通信开发框架。ACE自适配通信环境（Adaptive<br>&nbsp;Communication Environment）是可以自由使用、开放源代码的面向对象框架，在<br>其中实现了许多用于并发通信软件的核心模式。ACE提供了一组丰富的可复用C++包<br>装外观（Wrapper Facade）和框架组件，可跨越多种平台完成通用的通信软件任务<br>，其中包括：事件多路分离和事件处理器分派、信号处理、服务初始化、进程间通<br>信、共享内存管理、消息路由、分布式服务动态（重）配置、并发执行和同步，等<br>等。<br><br>　　(2) StreamModule<br><br>　　参考网站：http://www.omnifarious.org/StrMod/<br><br>　　设计用于简化编写分布式程序的库。尝试着使得编写处理异步行为的程序更容<br>易，而不是用同步的外壳包起异步的本质。<br><br>　　(3) SimpleSocket<br><br>　　参考网站：http://home.hetnet.nl/~lcbokkers/simsock.htm<br><br>　　这个类库让编写基于socket的客户/服务器程序更加容易。<br><br>　　(4) A Stream Socket API for C++<br><br>　　参考网站：http://www.pcs.cnu.edu/~dgame/sockets/socketsC++/sockets.h<br>tml<br><br>　　又一个对Socket的封装库。<br><br>　　5.5 XML<br><br>　　(1) Xerces<br><br>　　参考网站：http://xml.apache.org/xerces-c/<br><br>　　Xerces-C++ 是一个非常健壮的XML解析器，它提供了验证，以及SAX和DOM API<br>。XML验证在文档类型定义(Document Type Definition，DTD)方面有很好的支持，<br>并且在2001年12月增加了支持W3C XML Schema 的基本完整的开放标准。<br><br>　　(2) XMLBooster<br><br>　　参考网站：http://www.xmlbooster.com/<br><br>　　这个库通过产生特制的parser的办法极大的提高了XML解析的速度，并且能够产<br>生相应的GUI程序来修改这个parser。在DOM和SAX两大主流XML解析办法之外提供了<br>另外一个可行的解决方案。<br><br>　　(3) Pull Parser<br><br>　　参考网站：http://www.extreme.indiana.edu/xgws/xsoap/xpp/<br><br>　　这个库采用pull方法的parser。在每个SAX的parser底层都有一个pull的parse<br>r，这个xpp把这层暴露出来直接给大家使用。在要充分考虑速度的时候值得尝试。<br><br><br>　　(4) Xalan<br><br>　　参考网站：http://xml.apache.org/xalan-c/<br><br>　　Xalan是一个用于把XML文档转换为HTML，纯文本或者其他XML类型文档的XSLT处<br>理器。<br><br>　　(5) CMarkup<br><br>　　参考网站：http://www.firstobject.com/xml.htm<br><br>　　这是一种使用EDOM的XML解析器。在很多思路上面非常灵活实用。值得大家在D<br>OM和SAX之外寻求一点灵感。<br><br>　　(6) libxml++<br><br>　　http://libxmlplusplus.sourceforge.net/<br><br>　　libxml++是对著名的libxml XML解析器的C++封装版本<br><br>　　5.6 科学计算<br><br>　　(1) Blitz++<br><br>　　参考网站：http://www.oonumerics.org/blitz/<br><br>　　Blitz++ 是一个高效率的数值计算函数库，它的设计目的是希望建立一套既具<br>像C++ 一样方便，同时又比Fortran速度更快的数值计算环境。通常，用C++所写出<br>的数值程序，比 Fortran慢20%左右，因此Blitz++正是要改掉这个缺点。方法是利<br>用C++的template技术，程序执行甚至可以比Fortran更快。Blitz++目前仍在发展中<br>，对于常见的SVD，FFTs，QMRES等常见的线性代数方法并不提供，不过使用者可以<br>很容易地利用Blitz++所提供的函数来构建。<br><br>　　(2) POOMA<br><br>　　参考网站：http://www.codesourcery.com/pooma/pooma<br><br>　　POOMA是一个免费的高性能的C++库，用于处理并行式科学计算。POOMA的面向对<br>象设计方便了快速的程序开发，对并行机器进行了优化以达到最高的效率，方便在<br>工业和研究环境中使用。<br><br>　　(3) MTL<br><br>　　参考网站：http://www.osl.iu.edu/research/mtl/<br><br>　　Matrix Template Library(MTL)是一个高性能的泛型组件库，提供了各种格式<br>矩阵的大量线性代数方面的功能。在某些应用使用高性能编译器的情况下，比如In<br>tel的编译器，从产生的汇编代码可以看出其与手写几乎没有两样的效能。<br><br>　　(4) CGAL<br><br>　　参考网站：www.cgal.org<br><br>　　Computational Geometry Algorithms Library的目的是把在计算几何方面的大<br>部分重要的解决方案和方法以C++库的形式提供给工业和学术界的用户。<br><br>　　5.7 游戏开发<br><br>　　(1) Audio/Video 3D C++ Programming Library<br><br>　　参考网站：http://www.galacticasoftware.com/products/av/<br><br>　　AV3D是一个跨平台，高性能的C++库。主要的特性是提供3D图形，声效支持（S<br>B,以及S3M），控制接口（键盘，鼠标和遥感），XMS。<br><br>　　(2) KlayGE<br><br>　　参考网站：http://home.g365.net/enginedev/<br><br>　　国内游戏开发高手自己用C++开发的游戏引擎。KlayGE是一个开放源代码、跨平<br>台的游戏引擎，并使用Python作脚本语言。KlayGE在LGPL协议下发行。感谢龚敏敏<br>先生为中国游戏开发事业所做出的贡献。<br><br>　　(3) OGRE<br><br>　　参考网站：http://www.ogre3d.org<br><br>　　OGRE（面向对象的图形渲染引擎）是用C++开发的，使用灵活的面向对象3D引擎<br>。它的目的是让开发者能更方便和直接地开发基于3D硬件设备的应用程序或游戏。<br>引擎中的类库对更底层的系统库（如：Direct3D和OpenGL）的全部使用细节进行了<br>抽象，并提供了基于现实世界对象的接口和其它类。<br><br>　　5.8 线程<br><br>　　(1) C++ Threads<br><br>　　参考网站：http://threads.sourceforge.net/<br><br>　　这个库的目标是给程序员提供易于使用的类，这些类被继承以提供在Linux环境<br>中很难看到的大量的线程方面的功能。<br><br>　　(2) ZThreads<br><br>　　参考网站：http://zthread.sourceforge.net/<br><br>　　一个先进的面向对象，跨平台的C++线程和同步库。<br><br>　　5.9 序列化<br><br>　　(1) s11n<br><br>　　参考网站：http://s11n.net/<br><br>　　一个基于STL的C++库，用于序列化POD，STL容器以及用户定义的类型。<br><br>　　(2) Simple XML Persistence Library<br><br>　　参考网站：http://sxp.sourceforge.net/<br><br>　　这是一个把对象序列化为XML的轻量级的C++库。<br><br>　　5.10 字符串<br><br>　　(1) C++ Str Library<br><br>　　参考网站：http://www.utilitycode.com/str/<br><br>　　操作字符串和字符的库，支持Windows和支持gcc的多种平台。提供高度优化的<br>代码，并且支持多线程环境和Unicode，同时还有正则表达式的支持。<br><br>　　(2) Common Text Transformation Library<br><br>　　参考网站：http://cttl.sourceforge.net/<br><br>　　这是一个解析和修改STL字符串的库。CTTL substring类可以用来比较，插入，<br>替换以及用EBNF的语法进行解析。<br><br>　　(3) GRETA<br><br>　　参考网站：http://research.microsoft.com/projects/greta/<br><br>　　这是由微软研究院的研究人员开发的处理正则表达式的库。在小型匹配的情况<br>下有非常优秀的表现。<br><br>　　5.11 综合<br><br>　　(1) P::Classes<br><br>　　参考网站：http://pclasses.com/<br><br>　　一个高度可移植的C++应用程序框架。当前关注类型和线程安全的signal/slot<br>机制，i/o系统包括基于插件的网络协议透明的i/o架构，基于插件的应用程序消息<br>日志框架，访问sql数据库的类等等。<br><br>　　(2) ACDK - Artefaktur Component Development Kit<br><br>　　参考网站：http://acdk.sourceforge.net/<br><br>　　这是一个平台无关的C++组件框架，类似于Java或者.NET中的框架（反射机制，<br>线程，Unicode，废料收集，I/O，网络，实用工具，XML，等等），以及对Java, P<br>erl, Python, TCL, Lisp, COM 和 CORBA的集成。<br><br>　　(3) dlib C++ library<br><br>　　参考网站：http://www.cis.ohio-state.edu/~kingd/dlib/<br><br>　　各种各样的类的一个综合。大整数，Socket，线程，GUI，容器类,以及浏览目<br>录的API等等。<br><br>　　(4) Chilkat C++ Libraries<br><br>　　参考网站：http://www.chilkatsoft.com/cpp_libraries.asp<br><br>　　这是提供zip，e-mail，编码，S/MIME，XML等方面的库。<br><br>　　(5) C++ Portable Types Library (PTypes)<br><br>　　参考网站：http://www.melikyan.com/ptypes/<br><br>　　这是STL的比较简单的替代品，以及可移植的多线程和网络库。<br><br>　　(6) LFC<br><br>　　参考网站：http://lfc.sourceforge.net/<br><br>　　哦，这又是一个尝试提供一切的C++库<br><br>　　5.12 其他库<br><br>　　(1) Loki<br><br>　　参考网站：http://www.moderncppdesign.com/<br><br>　　哦，你可能抱怨我早该和Boost一起介绍它，一个实验性质的库。作者在loki中<br>把C++模板的功能发挥到了极致。并且尝试把类似设计模式这样思想层面的东西通过<br>库来提供。同时还提供了智能指针这样比较实用的功能。<br><br>　　(2) ATL<br><br>　　ATL(Active Template Library)<br><br>　　是一组小巧、高效、灵活的类，这些类为创建可互操作的COM组件提供了基本的<br>设施。<br><br>　　(3) FC++: The Functional C++ Library<br><br>　　这个库提供了一些函数式语言中才有的要素。属于用库来扩充语言的一个代表<br>作。如果想要在OOP之外寻找另一分的乐趣，可以去看看函数式程序设计的世界。大<br>师Peter Norvig在 &#8220;Teach Yourself Programming in Ten Years&#8221;一文中就将函<br>数式语言列为至少应当学习的6类编程语言之一。<br><br>　　(4) FACT!<br><br>　　参考网站：http://www.kfa-juelich.de/zam/FACT/start/index.html<br><br>　　另外一个实现函数式语言特性的库<br><br>　　(5) Crypto++<br><br>　　提供处理密码，消息验证，单向hash，公匙加密系统等功能的免费库。<br><br>　　还有很多非常激动人心或者是极其实用的C++库，限于我们的水平以及文章的篇<br>幅不能包括进来。在对于这些已经包含近来的库的介绍中，由于并不是每一个我们<br>都使用过，所以难免有偏颇之处，请读者见谅。<br><br>------------------------------------------------------------------------<br>--------<br><br>　　6，书籍<br><br>　　以前熊节先生曾撰文评论相对于Java程序设计语言，C++的好书多如牛毛。荣耀<br>先生在《程序员》杂志上撰文《C++程序设计之四书五经》也将本领域内几乎所有的<br>经典书籍作了全面的介绍,任何关于书的评论此时看来便是很多余的了。个人浅见，<br>除非你打算以C++作为唯一兴趣或者生存之本，一般读者确实没有足够的时间和必要<br>将20余本书籍全部阅读。更有参考价值的是荣耀先生的另一篇文章：《至少应该阅<br>读的九本C++著作》，可以从下面的地址浏览到此文：<br><br>　　http://www.royaloo.com/articles/articles_2003/9CppBooks.htm<br><br>　　下面几本书对于走在C++初学之路上的读者是我们最愿意推荐给大家的：<br><br>　　(1) 《C++ Primer》<br><br>　　哦，也许你会抱怨我们为什么不先介绍TCPL,但对于走在学习之路上的入门者，<br>本书内容更为全面，更为详细易懂，我们称它为&#8220;C++的超级宝典&#8221;并不过分。配有<br>一本不错的习题解答《C++ Primer Answer Book》可以辅助你的学习之路。<br><br>　　(2) 《Essential C++》<br><br>　　如果说《C++ Primer》是C++领域的超级宝典，那么此书作为掌握C++的大局观<br>当之无愧。正如《.NET大局观》一书能够让读者全揽.NET，本书讲述了C++中最核心<br>的全部主题。书虽不厚，内容精炼，不失为《C++ Primer》读者茶余饭后的主题回<br>顾之作。<br><br>　　(3) 《The C++ Programming Language》<br><br>　　Bjarne为你带来的C++教程，真正能够告诉你怎么用才叫真正的C++的唯一一本<br>书。虽然如同&#8220;某某程序设计语言&#8221;这样的书籍会给大家一个内容全揽，入门到精<br>通的感觉，但本书确实不太适合初学者阅读。如果你自认为是一名很有经验的C++程<br>序员，那至少也要反复咀嚼Bjarne先生所强调的若干内容。<br><br>　　(4) 《Effective C++》，《More Effective C++》<br><br>　　是的，正如一些C++爱好者经常以读过与没有读过上述两本作品来区分你是否是<br>C++高手。我们也极力推崇这两本著作。在各种介绍C++专家经验的书籍里面，这两<br>本是最贴近语言本质，看后最能够有脱胎换骨感觉的书，读此书你需每日三省汝身<br>。<br><br>　　技术书籍仁者见仁，过多的评论反无太多意义，由读者喜好选择最适合自己的<br>书方为上策。<br><br>------------------------------------------------------------------------<br>--------<br><br>　　7，资源网站<br><br>　　正如我们可以通过计算机历史上的重要人物了解计算机史的发展，C++相关人物<br>的网站也可以使我们得到最有价值的参考与借鉴，下面的人物我们认为没有介绍的<br>必要，只因下面的人物在C++领域的地位众所周知，我们只将相关的资源进行罗列以<br>供读者学习，他们有的工作于贝尔实验室，有的工作于知名编译器厂商，有的在不<br>断推进语言的标准化，有的为读者撰写了多部千古奇作&#8230;&#8230;<br>　　(1) Bjarne Stroustrup<br>　　http://www.research.att.com/~bs/<br><br>　　(2) Stanley B. Lippman<br>　　http://blogs.msdn.com/slippman/<br>　　中文版 http://www.zengyihome.net/slippman/index.htm<br><br>　　(3) Scott Meyers<br>　　http://www.aristeia.com/<br><br>　　(4) David Musser<br>　　http://www.cs.rpi.edu/~musser/<br><br>　　(5) Bruce Eckel<br>　　http://www.bruceeckel.com<br><br>　　(6) Nicolai M. Josuttis<br>　　http://www.josuttis.com/<br><br>　　(7) Herb Sutter<br>　　http://www.gotw.ca/<br><br>　　(8) Andrei Alexandrescu<br>　　http://www.coderncppdesign.com/<br><br>　　(9) 侯捷先生<br>　　http://www.jjhou.com<br><br>　　(10) 孟岩先生<br>　　先生繁忙于工作，痴迷于技术，暂无个人主页，关于先生的作品可以通过CSDN<br>的专栏和侯先生的主页访问到。<br><br>　　(11) 荣耀先生<br>　　http://www.royaloo.com/<br><br>　　(12) 潘爱民先生<br>　　http://www.icst.pku.edu.cn/panaimin/pam_homepage.htm<br><br>　　除了上述大师的主页外，以下的综合类C++学习参考站点是我们非常愿意向大家<br>推荐的：<br><br>　　(1) CodeProject<br>　　http://www.codeproject.com<br><br>　　(2) CodeGuru<br>　　http://www.codeguru.com<br><br>　　(3) Dr. Dobb's Journal<br>　　http://www.ddj.com<br><br>　　(4) C/C++ Users Journal<br>　　http://www.cuj.com<br><br>　　(5) C维视点<br>　　http://www.c-view.org<br><br>　　(6) allaboutprogram<br>　　http://www.allaboutprogram.com<br>　　其他资料<br><br>　　(1) ISO IEC JTC1/SC22/WG21 - C++：标准C++的权威参考<br>　　http://anubis.dkuug.dk/jtc1/sc22/wg21/<br><br>　　(2) C++ FAQ LITE — Frequently Asked Questions: 最为全面的C++FAQ<br>　　http://www.sunistudio.com/cppfaq/index.html<br>　　C/C++ 新闻组：<br>　　你不妨尝试从这里提问和回答问题，很多不错的Q&amp;A资源......<br><br>　　(1) .alt.comp.lang.learn.c-c++<br>　　这个简单些，如果你和我一样是个菜鸟<br><br>　　(2) .comp.lang.c++.moderated<br>&nbsp;&nbsp;&nbsp; 嗯，这个显然水平高一些<br><br>　　(3) .comp.std.c++<br>　　如果你需要讨论标准C++相关话题的话<br><br>------------------------------------------------------------------------<br>--------<br><br>　　8，不得不写的结束语<br><br>　　结束的时候也是总结现状，展望未来的时候。虽然C++从脱胎于C开始，一路艰<br>难坎坷的走过来，但是无论如何C++已经取得了工业基础的地位。文章列举的大量相关<br>资源就是最好的证明，而业界的大量用C++写成的产品代码以及大量的C++职业工程<br>师则是最直接的证明。同时，我们可以看到各个高校的计算机专业都开设有C++这门<br>课程，网络上对于C++的学习讨论也从来都没有停过。但是，在Java和.NET两大企业<br>开发平台的围攻下，给人的感觉是C++越来越&#8220;不行&#8221;了。<br><br>　　C++在面向企业的软件开发中，在开发便捷性等方面的确要比Java和C#差很多，<br>其中一个问题是C++语言本身比较复杂，学习曲线比较陡峭，另外一个问题是C++标<br>准化的时间太长，丧失了很多的壮大机会，耗费了很多精力在厂商的之间的斗争上<br>，而C++的标准库离一个完善的程序开发框架还缺少太多太多的内容，各个第三方的<br>类库和框架又在一致性和完整性上没法和随平台提供的框架相提并论。难道C++真的<br>要退出历史舞台了？<br><br>　　从C++目前的活跃程度，以及应用现状来说是完全能够肯定C++仍然是软件工业<br>的基础，也不会退出历史舞台的。另外从Boost，Loki这些库中我们也能够看到C++<br>的发展非常活跃，对于新技术新思维非常激进，C++仍然广泛受到关注。从ACE在高<br>性能通信领域的应用，以及MTL这样的库在数值计算领域的出色表现，我们可以看到<br>C++在高性能应用场合下的不可替代的作用，而嵌入式系统这样的内存受限开发平台<br>，比如Symbian OS上，C++已经发挥着并且将发挥更大的作用。可以预见的是以后的<br>软件无论上层的应用怎么变，它的底层核心都会是由C/C++这样的系统级软件编写的<br>，比如Java虚拟机，.NET Framwork。因为只有这样的系统级软件才能完全彻底的发<br>挥机器的功能。<br><br>　　需要看到的是两个趋势，一个趋势是C++变得更加复杂，更加学院派，通过模板<br>等有潜力的语法因素构造越来越精巧的库成为了现代C++的热点，虽然在利用库实现<br>新的编程范式，乃至设计模式等方面很有开创意义，也确实产生了一些能够便捷开<br>发的工具，但是更多的是把C++变得更加强大，更加复杂，也更加难懂，似乎也更加<br>学院派，不得不说它正在向边缘化道路发展。另一个趋势是C++在主流的企业应用开<br>发中已经逐渐退出了，ERP这样的企业软件开发中基本上不会考虑C++，除非需要考<br>虑性能或者和遗留代码的集成这些因素。C++退守到系统级别语言，成为软件工业的<br>基础是大势所趋。然而反思一下，真的是退守么？自从STL出现，无数的人风起云涌<br>的开始支持C++,他们狂呼&#8220;我看到深夜消失了，目标软件工程的出现。我看到了可<br>维护的代码。&#8221;是的，STL在可维护性下做得如此出色。但是又怎样呢？STL为C++铺<br>平了现代软件工程的道路，而在上层应用程序软件开发领域这块场地早不单独属于<br>C++,很多程序设计语言都做得很出色，疯狂的支持者会毫不犹豫地说我们应当支持<br>C++,因为它是世界上最棒的语言。而坦率地说，你的腰杆真的那么硬么？也许只是<br>在逃避一些事实。C++是优秀的，这不可否认，STL的出现让C++一度走上了最辉煌的<br>时刻，然而现在看来&#8230;&#8230;我的一位恩师曾言：真正能够将STL应用得淋漓尽致的人很<br>保守地说国内也不超过200人，或许不加入STL能够使C++向着它应当发展的方向发展<br>的更好，而现在看来，C++也应当回首到真正属于他的那一片圣地上&#8230;&#8230;<br><br>------------------------------------------------------------------------<br>--------<br><br>参考资料<br><br>本文成文时参考了以下资源：<br><br>1、《程序员》2004年2月，3月，&#8220;C++ 程序设计之四书五经&#8221; 荣耀<br><br>2、水'木清华BBS C++版精华区<br><br>3、http://jjhou.csdn.net<br><br>4、http://www.royaloo.com<br><br>5、http://www.zengyihome.net<br><br>6、C/C++ 开发人员：充实您的 XML 工具箱 http://www-900.ibm.com/developerW<br>orks/cn/xml/x-ctlbx/index.shtml<br><br>- 全文完 - <br><img src ="http://www.cppblog.com/paladino/aggbug/25664.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/paladino/" target="_blank">Gu.paladino</a> 2007-06-06 16:44 <a href="http://www.cppblog.com/paladino/articles/25664.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>