C++使用经验总结

写在前面

借着公司内和其他小组的一个分享,把自己几年来C++开发的一点思考总结一下。全篇没有高屋建瓴的观点,基本都是些细节方面的注意事项。希望能给大家提供一点帮助。

构建工具

C/C++世界里有不少的构建工具:make、autotools、scons、CMake、Bazel。但近几年比较流行的,也就是CMake和Bazel。所以这一部分,也就大概对比下这两个工具吧。

究竟该选择哪个工具,我觉得可以从如下几个方面来对比一下:

1. 上手难度

因为Bazel采用了类似Python的语法,所以其学习曲线相比CMake要平缓一些。但当我们考虑上手难度时,除了学习曲线之外,还要考虑文档的完备性、该工具的通用性等各个角度。当综合考虑时,我觉得CMake是一个尽管保守但仍旧不错的选择。主要原因就在于,CMake几乎已经成为现在C++的事实标准。使用CMake,就意味着:

  • 你可以把你熟悉CMake的技能用在折腾别的C++项目上。而这点之所以重要,是因为你在利用某个第三方库的时候,往往需要大概研究下它的编译过程。
  • CMake的官方文档和stackoverflow上的问答也比较完善。一旦遇到一个问题,往往通过搜索引擎能快速的得到答案。

另外,从设计理念上来看,CMake提供的解决方案是改革式的:它并没有提供一个全新的解决方案,而是和Make、Visual Studio或者其他现有的构建工具来结合使用的。而这就使得你无需丢弃在其他工具上所积累起来的开发经验——例如你熟悉make工具,哪怕是一个CMake维护的项目,你也可以毫不费力就知道如何来查看编译参数,以及控制编译并发度等等。

而对于Bazel则不是如此。Bazel完全以革命者的姿态完整提供了一整套解决方案,所有的使用细节你都要从头开始。加上文档的匮乏,这就使得你也得花上一段时间,才能熟悉Bazel。

2. thirdparty的管理

Bazel内置了对thirdparty源码级别依赖的支持

  • thirdparty可以是用Bazel构建的,也可以不是。对于非Bazel项目,你需要额外为其添加一个Bazel的描述文件。
  • thirdparty可以是一个本地项目,也可以是一个git仓库或者http链接

所以总的来看,Bazel对thirdparty支持还是非常友好的。

就这点对比来看,CMake其实做的是不太好的。CMake尽管也有ExternalProject的feature,但根据实际经验来看,使用和维护都比较的复杂。所以我还是更倾向于写几个脚本来下载和编译这些thirdparty依赖。

这里可以拿我参与维护的Pegasus项目为例。在该项目中,我们依赖了几个不同类型的项目:

  • 从构建工具上来看,这些依赖有使用CMake的,有使用make的,有使用autotools的
  • 从来源上来看,有的依赖来自git仓库,有的来自http链接,有的则是从一个大的项目里面挑选了一个更小的模块使用
  • 从代码的使用方式上来看,有的是直接拿来用,有的还需要稍微修改下源代码。

而通过shell脚本,这些各种各样的场景我们都能非常方便、直接、易维护的得以支持。

3. 其它

Bazel和CMake当然还有些其它方面值得对比,但并非一些通用的点,这里就简单列举下,不再详细展开了:

  • IDE集成
  • 缓存编译结果,从而加速编译过程
  • 多语言混合变成的支持
  • 分布式编译
  • 跨平台的支持

再补充一个别人的讨论链接, 有需求的可以参考一下。

编程规范

强烈推荐Google C++ Style。尽管它禁止了很多C++ feature而被很多人黑的很惨,但从工程的角度而言,它的确提供了非常多极其中肯的建议。说到底,编程规范的存在,主要就是可以让水平参差不齐的工程师们,可以在一起协作出风格较为一致的项目来。

也存在一些工具可以对google规范进行检查:

因为google的规范文档对C++ feature的取舍原因讲的非常好,这里就不再赘述了。唯一想补充的是异常

  • C++在语法层面对异常支持不太友好:你无法通过函数签名来得知一个函数到底会抛出哪些异常。例如:
    void GetSomeResource(const char* resource_name);
    
    如果这个接口没有良好文档或注释,并且也没有代码可翻时,你在调用这个接口时很有可能会漏掉一些错误情况——因为它可能抛出异常。更要命的是,一个疏于捕获的异常一旦触发,线上的程序就会crash。
    其实解释这么多,大家只要和Java中的异常机制对比一下,就高下立判了。对于这个话题,王垠的这篇博客值得一看的。
  • 在运维Pegasus项目时,遇到过一个老版本glibc的bug:如果多个线程同时抛出异常,程序会陷入死循环。这个bug的发现也是个有趣的过程,后面我专门写篇文章展开吧。
  • 在禁用异常后,程序就只能用错误码来进行错误处理。对于很多项目,大家都采用一套类似的范式,可以参考tensorflow的做法

C++的新特性

如果能使用C++的新特性,当然是尽量使用的好。我自己在开发中,觉得非常方便必须使用的新特性有:

  • 智能指针
  • 右值,以及C++14中右值得capture
  • lambda, bind
  • initialize list

想补充说一下的是auto,我自己不是特别喜欢这个feature,也非常赞同google规范中的对auto的限制:仅当可以提高代码可读性时,使用auto

这里不由得就想扯起java 10中的var。虽然能方便开发,但觉得更多的是会被滥用。而一个可能被滥用的feature,还不如没有的好。

第三方utility

在做项目开发的时候,一般会有很多琐碎的需求,从而也需要很多utility工具包。这里把我遇到的一些需求整理一下:

  • 算法和数据结构:stl, boost
  • 错误码管理:参见tensorflow
  • C语言的字符串封装:string_view
  • 字符串的各种操作、转换、打印:可以多翻翻abseil, 以及folly,另外也推荐fmtlib
  • 线程安全的、无锁的数据结构、线程池: folly
  • google全家桶:gtest,gflags, glog, protobuf, grpc

最后,也推荐下kudu这个项目,里面有自己实现的一些工具包,以及对google开源项目中utility的整理

单元测试

每个程序员都讨厌写测试。就我自己而言,我觉的单元测试的目的有以下几个:

  • 确保功能的实现和预期一致
  • 防止程序在重构的时候出问题
  • 给模块的使用者,提供使用示例

值得一提的是,对于C++项目,除了功能性测试之外,你最好还能让你的单元测试通过一些自动化工具的检测,如:

写在最后

自己的整理这些内容时,脑子里反复萦绕的一个问题是:我们在开发一个项目时,所要遵守的各种流程和规范到底是不是真的有必要的?说的更直白一点就是,“代码洁癖”这东西到底有没有意义?

我的看法是:代码洁癖不是一个原则,而是在投入和产出上的一种权衡。如果仅仅快速试错,那么就不需要维持代码洁癖,因为你完全不知道你今天写的代码究竟能存活多久。而如果是一个马拉松式的项目,代码洁癖就值得维持,因为它对于项目的维护的确很有意义。

最后,贴一个自己比较喜欢的C++博客

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,921评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,635评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,393评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,836评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,833评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,685评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,043评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,694评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,671评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,670评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,779评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,424评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,027评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,984评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,214评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,108评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,517评论 2 343

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,460评论 25 707
  • 用两张图告诉你,为什么你的 App 会卡顿? - Android - 掘金 Cover 有什么料? 从这篇文章中你...
    hw1212阅读 12,691评论 2 59
  • 1、通过CocoaPods安装项目名称项目信息 AFNetworking网络请求组件 FMDB本地数据库组件 SD...
    阳明先生_x阅读 15,967评论 3 119
  • 我是展鹏教育的大邢老师,这是我加入日记星球的第21篇原创日记。 今天展鹏教育旗下的展鹏作文、佳一数学秋季班课程全部...
    大邢老师阅读 335评论 0 2
  • 儿子最近太沉迷于手机,我有点不高兴,问题:你是想妈妈还是想妈妈的手机啊,他说:我是想你这个人,于是搂着我的脖子,开...
    薇薇shaw阅读 120评论 0 0