C++ Primer第五版之二:语言修订对写作策略的影响
openkk 12年前
<div id="news_body"> <p> 英文原文:<a href="/misc/goto?guid=4958522334231863620">C++ Primer 5th Edition, Part 2: How Language Revisions Change Strategy</a></p> <p> <a href="/misc/goto?guid=4958522334350898568" target="_blank">在上篇文章中,我提到了这样一个观点</a>: 作者在采取修订的方式写书的时候,把新的内容自然地融入到全书当中,比直接把所有新内容砸到一个章节里显得更加合理。不过采取这样的做法,会给读者的学习 造成一定的困难,尤其是在新加入的内容使得原有的知识更加抽象的前提下——根据我与 C++ 打交道 30 年来的经验,C++的发展一直是让这门语言越来越抽象的。</p> <p> 下面举个例子说明这种现象。给C语言加上类的支持的最初目的,是为了让 C++ 类能够向上兼容C的结构体。尤其是,在早期版本的拷贝构造函数里(大约是 1984 年左右的版本),如果没有显示定义拷贝构造函数,那么拷贝一个类的时候,仅仅是拷贝其内部的C结构体。那时的程序员管这种操作叫“按位拷贝” (bitwise copy)。这种拷贝行为在下面的例子中会产生问题:</p> <div class="cnblogs_code"> <pre><span style="color:#0000ff;">struct</span> Person { String firstname, lastname; };</pre> </div> <p> 当时还没有标准的 string 库,因此我使用 String 这个名字来强调这是一个用户自定义的类,用来实现多字符的串结构。</p> <p> 在早期的 C++ 版本中,这个类将会成为一个灾难。因为 String 类很可能包含了一个指针,这个指针会直接指向存放字符串内容的地址,指针在对 Person 对象进行拷贝时不会被简单地拷贝过去。这么做可能导致的结果就是,内存中的字符串和可能会面临两次 free 操作,一次是针对原来的 Person 对象,另一次是针对 Person 对象的拷贝。如此一来,使用这个版本 C++ 的程序员就必须提供显示的拷贝构造函数来避免这个问题。</p> <div class="cnblogs_code"> <pre><span style="color:#0000ff;">struct</span> Person { Person (<span style="color:#0000ff;">const</span> Person& p): firstname (p.firstname), lastname (p.lastname) { } <span style="color:#008000;">//</span><span style="color:#008000;"> and so on</span><span style="color:#008000;"> </span> String firstname, lastname; };</pre> </div> <p> 所有早期 C++ 版本的教学材料都会教给你上面的技术,因为如果你不这么做的话,即使最简单的抽象过程也会导致严重的 bug。显然,这些复杂的语言特性和随之带来的不便推动了对 C++ 语言默认行为的改进:在进行默认对象拷贝时,不会再直接拷贝类的C结构体,C++编译器会遍历源类的结构,并递归地拷贝所有对象元素到目标对象。</p> <p><a title="Barbara Moo——《C++ Primer 5th edition》的作者" rel="lightbox[25428]"><img style="display:block;margin-left:auto;margin-right:auto;" title="Barbara Moo——《C++ Primer 5th edition》的作者" alt="C++ Primer第五版之二:语言修订对写作策略的影响" src="https://simg.open-open.com/show/09a494ca3d8fbc83a1a621c2c8b6402f.jpg" width="245" height="327" /></a></p> <p style="text-align:center;">Barbara Moo——《C++ Primer 5th edition》的作者</p> <p> 设想如果你就是书的作者。通过你的书,你的程序练习例子,读者却感到使用显示拷贝构造函数是那么的困难,这多糟糕!还好,现在这门语言已经改进了,所有这些累赘的代码都不需要了。但是这时,还需要你作者干什么呢?</p> <p> 作为作者,你可以遍历全书,精于细节,找到每一个例子中曾经用到过那些累赘代码的片段,并进行简化或者彻底删掉重写,让各种细节都更加合理。或 者,你可以增加一些章节,比如像“如何使用 XXX 新特性”这样的章节,用来向读者说明,之前的那些繁文缛节的代码已经不再需要了。</p> <p> 尽管第二个做法看上去比第一个做法要省力很多,但是修订版(第五版)的《C++ Primer》却采用了第一种策略。在C++11的语法中,很多代码的书写方式已经被简化了,不需要再像以前那么麻烦了。这个特性会在很大程度上影响到本 书对于C++11关键知识点的介绍顺序。下周,我们会用具体的示例,来探讨一下 C++ 语言究竟有哪些改变。</p> <p> 英文原文:<a href="/misc/goto?guid=4958522334231863620" rel="nofollow" target="_blank">Andrew Koenig</a> 编译:<a href="/misc/goto?guid=4958338613453938753" target="_blank">伯乐</a>在线 – <a href="/misc/goto?guid=4958522334488180470" target="_blank">黄小非</a></p> <div id="come_from"> 来自: <a id="link_source2" href="http://blog.jobbole.com/25428/?utm_source=rss&utm_medium=rss&utm_campaign=c-primer%25e7%25ac%25ac%25e4%25ba%2594%25e7%2589%2588%25e4%25b9%258b%25e4%25ba%258c%25ef%25bc%259a%25e8%25af%25ad%25e8%25a8%2580%25e4%25bf%25ae%25e8%25ae%25a2%25e5%25af%25b9%25e5%2586%2599%25e4%25bd%259c%25e7%25ad%2596" target="_blank">blog.jobbole.com</a> </div> </div>