为什么 Boost 中的所有库都不是仅标头?换一种说法,是什么使 .lib/.dll 的使用成为强制性的?
是不是当一个类不能是模板或有静态字段时?
不同的点,我猜。
和一点安全感
如果 boost 库中有很多可访问的代码,或者编译器无法争论客户端是否可以访问的代码,则必须将其放入最终的二进制文件中。(*)
在具有包管理(例如基于 RPM 或 .deb)的操作系统上,共享库可能意味着二进制分发大小的大幅减少并具有安全优势:安全修复程序分发速度更快,然后所有 .so/ 自动使用.DLL 用户。所以你有一个重新编译和一个重新分发,但有N个奸商。使用仅包含头文件的库,您有N次重新编译、N次重新分发,总是针对每个修复程序,并且这些N中的某些成员本身已经很大。
(*) 可到达此处表示“可能执行”
一些 boost 库非常庞大。如果您愿意#include
,每次您在源文件中进行一些更改时,您都必须重新编译您所做的一切#include
。
这可以用樱桃采摘的标头来对抗,例如
#include <boost/huge-boost-library.hpp> // < BAD
#include <boost/huge-boost-library/just-a-part-of-it.hpp> // < BETTER
但有时你真正需要包含的东西已经大到足以削弱你的重新编译。
对策是使其成为静态或共享库,反过来意味着“完全编译一次(直到下一次 boost 更新)”。
我们还没有到一个全局优化可以解决我们所有的 C++ 性能问题的时代。为确保为编译器提供所需的所有信息,您可以只制作头文件并让编译器做出内联决策。
在这方面,请注意,由于 CPU 上的缓存和推测问题,内联并不总是提供卓越的性能。
另请注意,此论点主要与可能使用得足够频繁的 boost 库有关,例如,人们可能期望boost::shared_ptr<>
经常使用,因此是一个相关的性能因素。
但考虑到真正的唯一相关原因boost::shared_ptr<>
是只有标题......
C++ 中的一些东西不能放入库中,即模板和枚举。
但请注意,这只是对了一半。您可以为您的真实数据结构和算法编写类型安全的模板化接口,而这些接口又在库中具有它们的运行时通用实现。
同样,应该将C++ 中的一些内容放入源文件中,如果是 boost,则应放入库中。基本上,这就是所有会给出“多重定义”错误的东西,比如static
一般的成员变量或全局变量。
在标准库中也可以找到一些示例:在std::cout
标准中定义为extern ostream cout;
,因此cout
基本上需要分发定义一次且仅一次的东西(库或源文件) 。