多年C++开发使用经验总结

Yaphets123 · · 1576 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

摘要 借着公司内和其他小组的一个分享,把自己几年来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源码级别依赖的支持https://docs.bazel.build/versions/master/external.html: thirdparty可以是用Bazel构建的,也可以不是。对于非Bazel项目,你需要额外为其添加一个Bazel的描述文件。 thirdparty可以是一个本地项目,也可以是一个git仓库或者http链接 所以总的来看,Bazel对thirdparty支持还是非常友好的。 就这点对比来看,CMake其实做的是不太好的。CMake尽管也有ExternalProject https://cmake.org/cmake/help/latest/module/ExternalProject.html的feature,但根据实际经验来看,使用和维护都比较的复杂。所以我还是更倾向于写几个脚本来下载和编译这些thirdparty依赖。 这里可以拿我参与维护的Pegasus https://github.com/XiaoMi/rdsn/tree/master/thirdparty项目为例。在该项目中,我们依赖了几个不同类型的项目: 从构建工具上来看,这些依赖有使用CMake的,有使用make的,有使用autotools的 从来源上来看,有的依赖来自git仓库,有的来自http链接,有的则是从一个大的项目里面挑选了一个更小的模块使用 从代码的使用方式上来看,有的是直接拿来用,有的还需要稍微修改下源代码。 而通过shell脚本,这些各种各样的场景我们都能非常方便、直接、易维护的得以支持。 3、其它 Bazel和CMake当然还有些其它方面值得对比,但并非一些通用的点,这里就简单列举下,不再详细展开了: IDE集成 缓存编译结果,从而加速编译过程 多语言混合变成的支持 分布式编译 跨平台的支持 再补充一个别人的讨论Q群:731611386 编程规范 强烈推荐Google C++ Style:https://google.github.io/styleguide/cppguide.html。尽管它禁止了很多C++ feature而被很多人黑的很惨,但从工程的角度而言,它的确提供了非常多极其中肯的建议。说到底,编程规范的存在,主要就是可以让水平参差不齐的工程师们,可以在一起协作出风格较为一致的项目来。 也存在一些工具可以对google规范进行检查: clang-format https://clang.llvm.org/docs/ClangFormat.html cpplint https://github.com/cpplint/cpplint 因为google的规范文档对C++ feature的取舍原因讲的非常好,这里就不再赘述了。唯一想补充的是异常: C++在语法层面对异常支持不太友好:你无法通过函数签名来得知一个函数到底会抛出哪些异常。例如: void GetSomeResource(const char* resource_name); 如果这个接口没有良好文档或注释,并且也没有代码可翻时,你在调用这个接口时很有可能会漏掉一些错误情况——因为它可能抛出异常。更要命的是,一个疏于捕获的异常一旦触发,线上的程序就会crash。 其实解释这么多,大家只要和Java中的异常机制对比一下,就高下立判了。对于这个话题,王垠的这篇博客http://www.yinwang.org/blog-cn/2017/05/23/kotlin值得一看的。 在运维Pegasus项目时,遇到过一个老版本glibc的bug:如果多个线程同时抛出异常,程序会陷入死循环。这个bug的发现也是个有趣的过程,后面我专门写篇文章展开吧。 在禁用异常后,程序就只能用错误码来进行错误处理。对于很多项目,大家都采用一套类似的范式,可以参考tensorflow的做法https://github.com/tensorflow/tensorflow/blob/master/tensorflow/core/lib/core/status.h C++的新特性 如果能使用C++的新特性,当然是尽量使用的好。我自己在开发中,觉得非常方便必须使用的新特性有: 智能指针 右值,以及C++14中右值得capture lambda, bind initialize list 想补充说一下的是auto,我自己不是特别喜欢这个feature,也非常赞同google规范中的对auto的限制:仅当可以提高代码可读性时,使用auto 这里不由得就想扯起java 10中的var。虽然能方便开发,但觉得更多的是会被滥用。而一个可能被滥用的feature,还不如没有的好。 第三方utility 在做项目开发的时候,一般会有很多琐碎的需求,从而也需要很多utility工具包。这里把我遇到的一些需求整理一下: 算法和数据结构:stl, boost 错误码管理:参见tensorflowhttps://github.com/tensorflow/tensorflow/blob/master/tensorflow/core/lib/core/status.h C语言的字符串封装:string_view https://github.com/abseil/abseil-cpp/blob/master/absl/strings/string_view.h 字符串的各种操作、转换、打印:可以多翻翻abseil https://github.com/abseil/abseil-cpp, 以及folly https://github.com/facebook/folly,另外也推荐fmtlibhttps://github.com/fmtlib/fmt 线程安全的、无锁的数据结构、线程池: folly google全家桶:gtest,gflags, glog, protobuf, grpc 最后,也推荐下kudu这个项目,里面有自己实现的一些工具包https://github.com/cloudera/kudu/tree/master/src/kudu/util,以及对google开源项目中utility的整理https://github.com/cloudera/kudu/tree/master/src/kudu/gutil。 单元测试 每个程序员都讨厌写测试。就我自己而言,我觉的单元测试的目的有以下几个: 确保功能的实现和预期一致 防止程序在重构的时候出问题 给模块的使用者,提供使用示例 值得一提的是,对于C++项目,除了功能性测试之外,你最好还能让你的单元测试通过一些自动化工具的检测,如: valgrind:检查内存泄露,以及非法访存 Address Sanitizer:检测非法访存https://github.com/google/sanitizers/wiki/AddressSanitizer Thread Sanitizer:检测线程竞争https://clang.llvm.org/docs/ThreadSanitizer.html 写在最后 自己的整理这些内容时,脑子里反复萦绕的一个问题是:我们在开发一个项目时,所要遵守的各种流程和规范到底是不是真的有必要的?说的更直白一点就是,“代码洁癖”这东西到底有没有意义? 我的看法是:代码洁癖不是一个原则,而是在投入和产出上的一种权衡。如果仅仅快速试错,那么就不需要维持代码洁癖,因为你完全不知道你今天写的代码究竟能存活多久。而如果是一个马拉松式的项目,代码洁癖就值得维持,因为它对于项目的维护的确很有意义。 最后,贴一个C语言学习交流群:731611386 以上为今天的分享内容,谢谢大家!

有疑问加站长微信联系(非本文作者))

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

1576 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传