Linux多线程服务端编程:使用muduo C++网络库 学习笔记 附录C 关于Boost的看法

这是作者为电子工业出版社出版的《Boost程序库完全开发指南》写的推荐序,此处节选了作者对在C++工程项目中使用Boost的看法。

最近一年(这篇文章写于2010年8月)作者电话面试了数十位C++应聘者。惯用的暖场问题是“工作中使用过STL的哪些组件?使用过Boost的哪些组件?”。得到的答案大多集中在vector、map、shared_ptr。如果对方是在校学生,作者一般会问问vector或map的内部实现、各种操作的复杂度以及迭代器失效的可能场景。如果是有经验的程序员,作者还会追问shared_ptr的线程安全性、循环引用的后果及如果避免、weak_ptr的作用等。如果这些都回答得不错,进一步还可以问问如何实现线程安全的引用计数,如果定制删除动作等等。这些问题让作者能迅速辨别对方的C++水平。

作者之所以在面试时问到Boost,是因为其中的某些组件确实可以用于编写可维护的产品代码。Boost包含近百个程序库,其中不乏具有工程实用价值的佳品。每个人的口味与技术背景不一样,对Boost的取舍也不一样。就作者的个人经验而言,首先可以使用绝对无害的库,例如noncopyable、scoped_ptr、static_assert等,这些库的学习和使用都比较简单,容易入手。其次,有些功能自己实现起来并不困难,正好Boost里提供了现成的代码,那就不妨一用,比如date_time(注意boost::date_time处理时区和夏令时采用的方法不够灵活,可以考虑使用muduo::TimeZone)和circular_buffer等等。然后,在新项目中,对于消息传递和资源管理可以考虑采用更加现代的方式,例如用function/bind在某些情况下代替虚函数作为库的回调接口、借助shared_ptr实现线程安全的对象回调等等。这二者会影响整个程序的设计思路与风格,需要通盘考虑,如果正确使用智能指针,在现代C++里一般不需要出现delete语句。最后,对某些性能不佳的库保持警惕,比如lexical_cast(一个用于在不同数据类型之间进行转换的通用工具,如将字符串转换为数字,将数字转换为字符串,以及其他基本数据类型之间的转换)。总之,在项目组成员人人都能理解并运用的基础上,适当引入现成的Boost组件,以减少重复劳动,提高生产力。

试举一例:正则表达式库regex对线程安全的处理。早期的RegEx class不是线程安全的,它把“正则表达式”和“匹配动作”放到了一个class里边。由于有可变数据,RegEx的对象不能跨线程使用。如今的regex明确地区分了不可变(immutable)与可变(mutable)的数据,前者可以安全地跨线程共享,后者则不行。比如正则表达式本身(basic_regex)与一次匹配的结果(match_results)是不可变的;而匹配动作本身(match_regex)设计状态更新,是可变的,于是用可重入的函数将其封装起来,不让这些数据泄露给别的线程。正是由于做了这样合理的区分,regex在正常使用时就不必加锁。

Donald Knuth在《Coders at Work》一书里表达了这样一个观点:如果程序员的工作就是摆弄参数去调用现成的库,而不知道这些库是如何实现的,那么这份职业就没啥乐趣可言。换句话说,固然强调工作中不要重新发明轮子,但是作为一个合格的程序员,应该具备自制轮子的能力。非不能也,是不为也。

C/C++语言的一大特点是其标准库可以用语言自身实现。C标准库的strlen、strcpy、strcmp系列函数是教学与练习的好题材,C++标准库的complex、string、vector则是class、资源管理、模板编程的绝佳示范。在深入了解STL的实现之后,运用STL自然手到擒来,并能自动避免一些错误和低效的用法。

对于Boost也是如此,为了消除使用时的异或,为了用得更顺手,有时我们需要适当了解其内部实现,甚至编写简化版用作对比验证。但是由于Boost代码用到了日常应用程序开发中不常见的高级语法和技巧,并且为了跨多个平台和编译器而大量使用了预处理宏,阅读Boost源码并不轻松惬意,需要下一番工夫。另一方面,如果沉迷于这些有趣的底层细节而忘了原本要解决什么问题,恐怕就舍本逐末了。

Boost中的很多库是按泛型编程(generic programming)的范式来设计的,对于熟悉面向对象编程的人而言,或许面临一个思路的转变。比如,你得熟悉泛型编程的那套术语,如concept、model、refinement,才容易读懂Boost.Threads的文档中关于各种锁的描述。对于熟悉STL设计理念的人而言,这不是什么大问题。

在某些领域,Boost不是唯一的选择,也不一定是最好的选择。比如,要生成公式化的源代码,坐着宁愿用脚本语言写一小段代码生成程序,而不用Boost.Preprocessor(Boost C++库中的一个组件,旨在提供一组预处理器宏,用于在编译时生成重复代码、元编程和其他需要在预处理阶段处理的任务);要在C++程序中嵌入领域特定语言,作者宁愿用Lua或其他语言解释器,而不用Boost.Proto(允许用户定义自己的表达式语法,以及对应的语法规则和操作。这使得用户可以根据自己的需求定义符合领域特定需求的表达式语法,从而编写更加简洁和易读的代码);要用C++程序解析上下文无关文法,作者宁愿用ANTLR(ANother Tool for Language Recognition,一个用于构建语言识别器、解析器和翻译器的工具)来定义词法与语法规则并生成解析器(parser),而不用Boost.Spirit(一个用于构建解析器和生成器的工具库,能够让开发者使用C++中的语法进行递归下降解析和生成操作)。总之,使用Boost时心态要平和,别较劲去改造C++语言。把它有助于提高生产力的那部分功能充分发挥出来,让项目从中受益才是关键。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值