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

📄 appendix_b.html

📁 制作本书的目的是为了方便大家的阅读。转载时请保持本电子书的完整性。 前言、条款2、16、21、44根据从Addison-Wesley出版社下载的开放条款翻译。条款26、27、28、45根据从Sc
💻 HTML
字号:
<?xml version="1.0" encoding="gb2312"?><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><title>附录B:在微软STL平台上的注意事项</title><link href="css/all.css" rel="stylesheet" type="text/css" /><meta http-equiv="Content-Type" content="text/html; charset=gb2312" /></head><body><h1>在微软STL平台上的注意事项</h1><p>在这本书的开头几页里,我提到了术语<dfn>STL平台</dfn>是指一个特定编译器和一个标准模板库特定实现的组合。如果你在使用版本6或更早的Microsoft Visual C++编译器(即,伴随版本6或更早的Microsoft Visual Studio的编译器),在编译器和库之间的区别特别重要,因为编译器有时比伴随的STL实现更有能力。在本附录中,我描述了旧的微软STL平台的一个重要缺点,而且我提供可以明显改进你STL经验的变通办法。</p><p>下面是给使用Microsoft Visual C++(MSVC)4-6版的开发者的信息。如果你正使用Visual C++ .NET,你的STL平台没有下面描述的那些问题,你可以略过这个附录。</p><h2>STL里的成员函数模板</h2><p>假设你有两个Widget的vector,你想把一个vector里的Widget拷贝到另一个的末端。那很容易。只要使用vector的区间insert函数(参见<a href="item_05.html">条款5</a>):</p><pre>vector&lt;Widget&gt; vw1, vw2;...vw1.insert(vw1.end(), vw2.begin(), vw2.end());		// 把vw2里Widget的副本							// 追加到vw1</pre><p>如果你有一个vector和一个deque,你一样可以这么做:</p><pre>vector&lt;Widget&gt; vw;deque&lt;Widget&gt; dw;vw.insert(vw.end(), dw.begin(), dw.end());			// 把dw里Widget的副本							// 追加到vw</pre><p>实际上,你不必理会被拷贝的容器容纳的是什么类型的对象。即使自定义容器也可以工作:</p><pre>vector&lt;Widget&gt; vw;...list &lt;Widget&gt; lw;...vw.insert(vw.begin(), lw.begin(), lw.end());			// 把lw里Widget的副本							// 追加到vwset&lt;Widget&gt; sw;...vw.insert(vw.begin(), sw.begin(), sw.end());			// 把sw里Widget的副本							// 追加到vwtemplate&lt;typename T,					// 用于自定义	typename Allocator = allocator&lt;T&gt; &gt;			// 兼容STL的class SpecialContainer { ... };				// 容器模板SpecialContainer&lt;Widget&gt; scw;...vw.insert(vw.end(), scw.begin(), scw.end());			// 把scw里Widget的副本							// 追加到vw</pre><p>这种灵活性是可能的,因为vector的区间insert函数完全不是一个函数。相反,它是一个<dfn>成员函数模板</dfn>,可以用任何<em>迭代器类型</em>实例化,以产生一个具体的区间insert函数。对于vector,标准像这样声明insert模板:</p><pre>template &lt;class T, class Allocator = allocator&lt;T&gt; &gt;class vector {public:	...	template &lt;class InputIterator&gt;	void insert(iterator position, InputIterator first, InputIterator last);	...};</pre><p>每个标准容器都要求提供这个模板化的区间insert。容器也要求提供类似成员函数模板的区间构造函数和assign的区间形式(两者都在<a href="item_05.html">条款5</a>讨论)。</p><h2>MSVC版本4-6</h2><p>不幸的是,伴随MSVC版本4-6的STL实现没有声明成员函数模板。这个库最初为MSVC版本4开发,而那个编译器,像它所在时代的大多数编译器一样,缺乏成员函数模板的能力。在MSVC4到MSVC6之间,编译器增加了对这些模板的支持,但是,由于法律诉讼的影响,微软没有直接包含它们,库基本保持冻结。</p><p>因为伴随MSVC4-6的STL实现是为一个缺乏成员函数模板的编译器设计的,库的作者通过用具体函数替换每个模板的方法来近似这样的功能性,也就是只接受和容器的迭代器类型相同的迭代器。例如,对于insert,这个成员函数模板被替换这样:</p><pre>void insert(iterator position,				// “iterator”是		iterator first, iterator last);		// 容器的迭代器类型</pre><p>受限的区间成员函数形式可以进行从一个vector&lt;Widget&gt;到一个vector&lt;Widget&gt;或从一个list&lt;int&gt;到一个list&lt;int&gt;的区间插入,但不能从一个vector&lt;Widget&gt;到一个list&lt;Widget&gt;或从一个set&lt;int&gt;到一个deque&lt;int&gt;。甚至不可能进行从一个vector&lt;long&gt;到一个vector&lt;int&gt;的区间insert(或assign或构造),因为vector&lt;long&gt;::iterator与vector&lt;int&gt;::iterator类型不同。结果,下面十分有效的代码不能用MSVC4-6编译:</p><pre>istream iterator&lt;Widget&gt; begin(cin), end;			// 建立用于从cin							// 读取Widget的							// begin和end迭代器							// (参见<a href="item_06.html">条款6</a>)vector&lt;Widget&gt; vw(begin, end);				// 把cin的Widget读入vw							// (再次参见<a href="item_06.html">条款6</a>);<em>在MSVC4-6</em>							// <em>不能编译</em>list&lt;Widget&gt; lw;...lw.assign(vw.rbegin(), vw.rend());				// 把vw的内容赋值给lw							// (以反序);<em>在MSVC4-6</em>							// <em>不能编译</em>SpecialContainer&lt;Widget&gt; scw;...scw.insert(scw.end(), lw.begin(), lw.end());			// 把lw中的Widget的副本							// 插入scw的末端;							// <em>在MSVC4-6不能编译</em></pre><p>那如果你必须使用MSVC4-6,你该怎么办?那取决于你使用的MSVC版本和是否你被迫使用伴随编译器的STL实现。</p><h2>MSVC4-5的变通办法</h2><p>再次看看不能用伴随MSVC4-6的STL编译的有效代码例子:</p><pre>vector&lt;Widget&gt; vw(begin, end);				// 被MSVC4-6的							// STL实现拒绝list&lt;Widget&gt; lw;...lw.assign(vw.rbegin(), vw.rend());				// 也拒绝SpecialContainer&lt;Widget&gt; scw;...scw.insert(scw.end(), lw.begin(), lw.end());	// 同上</pre><p>这些调用看起来相当不同,但它们全都由于相同的原因而失败:在STL实现里缺乏成员函数模板。对它们有一种单独的治疗方法:使用copy和插入迭代器(参见<a href="item_30.html">条款30</a>)。例如,这里是上面例子的变通办法:</p><pre>istream_iterator&lt;Widget&gt; begin(cin), end;vector&lt;Widget&gt; vw;						// 默认构造vw;copy(begin, end, back_inserter(vw));				// 然后把cin中的							// Widget拷贝进去list&lt;Widget&gt; lw;...lw.clear();						// 去除lw的老copy(vw.rbegin(), vw.rend(), back_inserter(lw));		// Widget;把							// vw的Widget拷贝进去(以							// 反序)SpecialContainer&lt;Widget&gt; scw;...copy(lw.begin(), lw.end(),					// 把lw的Widget拷贝到	inserter(scw, scw.end()));				// scw的结尾</pre><p>我鼓励你在伴随MSVC4-5的库上使用这样的基于copy的变通办法,但是注意!不要满足于这个变通办法,你忘记了它们只是<em>变通办法</em>。正如<a href="item_05.html">条款5</a>解释的,使用copy算法几乎总是不如使用一个区间成员函数,所以一旦你有机会把你的STL平台升级到支持成员函数模板的版本,就在区间成员函数是正确方法的地方停止使用copy。</p><h2>用于MSVC6的另一个变通办法</h2><p>你也可以对MSVC6使用MSVC4-5的变通办法,但对于MSVC6有另一个选择。作为MSVC4-5一部分的编译器没有提供有意义的成员函数模板,所以STL实现缺乏它们的事实是无关紧要的。MSVC6的形势则不同,因为MSVC6的编译器支持成员函数模板。因此有理由考虑用提供标准指定的成员函数模板的STL实现替换伴随MSVC6的。</p><p><a href="item_50.html">条款50</a>解释了SGI和STLport都提供了可以自由下载的STL实现,而且那两个实现都把MSVC6编译器作为将配合的编译器之一。你也可以从Dinkumware购买最新的兼容MSVC的STL实现。每种选择各有利弊。</p><p>SGI的和STLport的实现是自由的,我想你知道那在对软件的官方支持上代表什么:完全没有。而且,因为SGI和STLport把他们的库设计为使用多种编译器,你或许必须手工配置它们的实现来最有效地使用MSVC6。特别是,你可能必须明确地启用成员函数模板的支持,因为,它们要使用很多编译器,SGI和/或STLport默认可能不启用它。你可能也得为与其他MSVC6库(特别是DLL)链接而担心,包括保证你使用合适的线程和调试构建,等等。</p><p>如果你被那些事吓着了,或如果你听过你负担不起自由软件的牢骚,你可能要看看Dinkumware用于MSVC6的替代库。它被设计为提高原生MSVC6 STL的兼容性,并使作为STL平台的MSVC6对标准的支持最大化。因为Dinkumware写了伴随MSVC6的STL,所以他们最新的STL实现有很大的可能性真的<em>是</em>一个合适的替代品。要了解更多关于Dinkumware STL实现的信息,访问公司的网站:<a href="http://www.dinkumware.com/">http://www.dinkumware.com/</a>。</p><p>不管你选择的是SGI的、STLport的还是Dinkumware的实现作为STL的替代品,你将得到的不只是带有成员函数模板的STL。你也将在库的其他地方旁路一致性问题,比如没有声明push_back的string。此外,你可以访问有用的STL扩展,包括散列容器(参见<a href="item_25.html">条款25</a>)和单链表(slists)。SGI的和STLport的实现也提供了多种非标准的仿函数类,比如select1st和select2nd(参见<a href="item_50.html">条款50</a>)。</p><p>即使你被伴随MSVC6的STL实现困住,访问Dinkumware网站或许也是值得的。那个网站列举了在MSVC6的库实现里的已知漏洞并解释怎样修改你的库副本来减少它的缺陷。不用说,编辑你的库头文件是让你自己冒险的事。如果你遇到麻烦,不要责备我。</p></body></html>

⌨️ 快捷键说明

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