我一直非常喜欢boost,自从2004年无意中发现它。当时我就惊呆了,心里想如此庞大完整的程序库,只要学会了它,一辈子都够用了。
从那以后我一直对boost保持关注,也用它来开发一些小工具,每次boost升级,我都会第一时间更新,从源码经过漫长的编译升级以后,浑身上下一阵神清气爽的感觉,仿佛我自己也经历了一次蜕变。
多年以后我有机会从头做一个项目,作为负责人自己寻找解决方案,在第三方库的选择方面,我最终放弃了boost,而且至今一直禁止在我的团队中使用boost。
性能问题
boost的某些库有性能问题,比如说boost::format比snprintf慢20甚至30倍以上。当然不是说boost::format就不能用了,要看场合,比如说客户端程序,调用频率不高,就可以用,而服务器端程序,调用频繁,就不适合了。
boost里面性能不佳的库肯定不止这一个,每次在自己使用之前最好都做一下性能测试,看看是否满足自己的需求。当然这个测试就要花点时间了,而且每次升级到新版本,都要测试一下。boost升级蛮频繁的。
too old
boost的强项是跨平台,并且支持N个编译器,甚至支持一些古老的编译器。为了支持那些古老的编译器,boost代码里面用了无数宏。但是C++11出来以后,很多特性使得编写程序库更容易了,于是github上出现了很多比boost中同类型库更优秀的程序库。比如说pybind11,就比boost::python用起来方便很多,借助C++11的模板特性,pybind11的实现也要简洁得多。
那些bug
每个版本的Release Notes都有不少bug的更新,这说明boost其实是有不少bug的。例如某个版本Release Notes关于某个库的部分内容:
Fixed bugs:
Trac #11627: "small_vector<T,n>::swap() appears to be broken".
Trac #11628: "small_vector<int,n> iterates over elements in destructor".
Trac #11697: "Wrong initialization order in tuple copy-constructor".
Trac #11698: "Missing return statement in static_storage_allocator".
GitHub #29: Doc fixes for flap_map complexity requirements.
GitHub #31: DL_SIZE_IMPL also dereference addr.
类似这样的东西不少,看得眼花缭乱,或许有些是和平台有关的,我们的gcc没有碰到,也或许某些bug相关的功能根本不常用。但是,如何区分哪些bug对我们有影响哪些没有,绝不是容易的事情,况且还有发现了但是没有被fix掉的和没有发现的bug呢。
新旧版本的兼容
我自己常常用boost来写一些小工具,某次boost升级以后发现之前的代码编不过了,仔细一看,原来是用到的filesystem库发生了接口的变更,得修改使用该接口的代码,改成调用新的函数后来才编译通过。
![](https://img.jasve.com/2024-2/8878f3d9ba6f8ca8586f58d83c8537c3.webp)
还有一些其它原因全部发出来好几千字,太长了也没人看,就此打住了。总之对我来说,boost作为一个全家桶,会给管理和维护带来麻烦。
其实google的c++编码规范里面也用了boost,但是他们是有选择地规定只能用哪几个,甚至只能用某个库的某些部分的功能。如果决定要在团队中使用boost,最好也是像这样根据项目需求建立一个白名单。
当然boost肯定是一个非常优秀的C++库,我平时的很多工具依然离不开它,但是我更喜欢去学习它的源码,造自己的轮子。boost的协程里面的那几个汇编代码,可以直接拿出来用,打造自己的协程库;我之前也参考boost::serialize写了一个简单的序列化库,只用了几百行,因为我只需要使用部分功能而已,但是对我的项目来说完全满足了。
其实,用C++最大的乐趣就是造轮子,提高C++编程水平最好的方法也是造轮子。知其然并知其所以然,才能完成编程能力的蜕变。
boost也不过是一个(些)C++轮子。每个C++轮子的价值不仅仅是给别人使用,也是给其他人造轮子提供参考。不直接使用boost而是参考boost造自己的轮子这种心态,其实也是在使用boost,而且比直接使用更为彻底。