专栏首页编程学习基地如何写出优雅的C++代码

如何写出优雅的C++代码

# 干了这碗鸡汤

不要否定自己的未来,未来会很晴朗,好运也在路上。

工欲善其事必先利其器,优雅的代码离不开静态代码检查工具,大家可能平时使用较多的是cppcheck,但今天我想跟大家分享另一个静态代码检查工具clang-tidy。

不同于cppcheck使用正则表达式进行静态代码分析,clang-tidy是基于语法分析树的静态代码检查工具,虽然它的速度比正则表达式慢一些,但是它检查的更准确、全面,而且不仅可以做静态检查,还可以做一些修复工作,自行添加一些自定义检查规则。

话不多说,上代码:

#include <iostream>

int main() {
    int a = 1.2;
    return 0;
}

这里有隐式类型转换,可以使用clang-tidy来检测:

~/test$ clang-tidy -checks=* test_lint.cpp --
7748 warnings generated.
/home/wangzhiqiang/test/test_lint.cpp:20:13: warning: implicit conversion from 'double' to 'int' changes value from 1.2 to 1 [clang-diagnostic-literal-conversion]
    int a = 1.2;
            ^
Suppressed 7747 warnings (7747 in non-user code).
Use -header-filter=.* to display errors from all non-system headers. Use -system-headers to display errors from system headers as well.

这里也许你有疑问了,这不就是一个普通的编译警告嘛,正常使用编译器也可以检查出来,那再看一段代码:

#include <iostream>

int main() {
    char* d = NULL;
    return 0;
}

我们都知道在C++中应该更多的使用nullptr而不是NULL,这里使用了NULL而不是使用nullptr,可能我们在开发过程中没有注意到这种用法,所以clang-tidy派上了用场:

~/test$ clang-tidy -checks=* test_lint.cpp --
7748 warnings generated.
/home/wangzhiqiang/test/test_lint.cpp:20:15: warning: use nullptr [modernize-use-nullptr]
    char* d = NULL;
              ^~~~~
              nullptr
Suppressed 7747 warnings (7747 in non-user code).
Use -header-filter=.* to display errors from all non-system headers. Use -system-headers to display errors from system headers as well.

再举一个例子:

struct Base {
    virtual void func() {

    }
};

struct Derive : Base {
    virtual void func() {

    }
};

这里可能我们乍一看没有任何问题,其实在C++11里派生类继承父类,重写了某些函数时最好加上override关键字,通过clang-tidy还是可以检测出来:

~/test$ clang-tidy -checks=* test_lint.cpp --
7749 warnings generated.
/home/wangzhiqiang/test/test_lint.cpp:14:18: warning: prefer using 'override' or (rarely) 'final' instead of 'virtual' [hicpp-use-override]
    virtual void func() {
    ~~~~~~~~~~~~~^
                        override
Suppressed 7747 warnings (7747 in non-user code).
Use -header-filter=.* to display errors from all non-system headers. Use -system-headers to display errors from system headers as well.

该工具还可以检查代码是否符合编码规范,例如Google编码规范等,看这段头文件相关代码:

#include <iostream>
#include <string>
#include <memory>

这里其实有一点点问题,头文件引用顺序不满足编码规范,这里其实clang-format都可以检测出来,但clang-tidy也可以检测出来,通过-fix还可以进行自动修复:

~/test$ clang-tidy -checks=* test_lint.cpp --
8961 warnings generated.
/home/wangzhiqiang/test/test_lint.cpp:2:1: warning: #includes are not sorted properly [llvm-include-order]
#include <string>
^        ~~~~~~~~
Suppressed 8960 warnings (8960 in non-user code).
Use -header-filter=.* to display errors from all non-system headers. Use -system-headers to display errors from system headers as well

它还可以检测隐藏的内存泄漏:

int main() {
    char* ct = (char*)malloc(323);
    return 0;
}

这是使用clang-tidy的检测结果:

~/test$ clang-tidy -checks=* test_lint.cpp --
7756 warnings generated.
/home/wangzhiqiang/test/test_lint.cpp:20:5: warning: initializing non-owner 'char *' with a newly created 'gsl::owner<>' [cppcoreguidelines-owning-memory]
    char* ct = (char*)malloc(323);
    ^
/home/wangzhiqiang/test/test_lint.cpp:20:5: warning: use auto when initializing with a cast to avoid duplicating the type name [hicpp-use-auto]
    char* ct = (char*)malloc(323);
    ^~~~~
    auto
/home/wangzhiqiang/test/test_lint.cpp:20:11: warning: Value stored to 'ct' during its initialization is never read [clang-analyzer-deadcode.DeadStores]
    char* ct = (char*)malloc(323);
          ^
/home/wangzhiqiang/test/test_lint.cpp:20:11: note: Value stored to 'ct' during its initialization is never read
/home/wangzhiqiang/test/test_lint.cpp:20:16: warning: C-style casts are discouraged; use static_cast [google-readability-casting]
    char* ct = (char*)malloc(323);
               ^~~~~~~~~~~~~     ~
               static_cast<char*>( )
/home/wangzhiqiang/test/test_lint.cpp:20:16: warning: do not use C-style cast to convert between unrelated types [cppcoreguidelines-pro-type-cstyle-cast]
/home/wangzhiqiang/test/test_lint.cpp:20:23: warning: do not manage memory manually; consider a container or a smart pointer [cppcoreguidelines-no-malloc]
    char* ct = (char*)malloc(323);
                      ^
/home/wangzhiqiang/test/test_lint.cpp:21:5: warning: Potential leak of memory pointed to by 'ct' [clang-analyzer-unix.Malloc]
    return 0;
    ^
/home/wangzhiqiang/test/test_lint.cpp:20:23: note: Memory is allocated
    char* ct = (char*)malloc(323);
                      ^
/home/wangzhiqiang/test/test_lint.cpp:21:5: note: Potential leak of memory pointed to by 'ct'
    return 0;
    ^
Suppressed 7747 warnings (7747 in non-user code).
Use -header-filter=.* to display errors from all non-system headers. Use -system-headers to display errors from system headers as well

clang-tidy还有很多高端功能,大概可以检测出250种问题,大体主要分为几大类:

  • abseil:检测abseil库的相关问题
  • android:检测Android相关问题
  • boost:检测boost库的相关问题
  • cert:检测CERT的代码规范
  • cpp-core-guidelines:检测是否违反cpp-core-guidelines
  • google:检测是否违反google编码规范
  • llvm:检测是否违反llvm编码规范
  • performance:检测性能相关的问题
  • readability:检测与可读性相关,但又不属于某些编码规范的问题
  • modernize:检测是否使用现代C++11相关的代码问题

而且适用于Windows/Linux/MacOS多平台,还支持命令行,CLion/VSCode/VSStudio插件等,检测规则还可以定制,重要的是免费开源,快去用起来吧,写出优雅的C++代码~

参考资料:

https://clang.llvm.org/extra/clang-tidy/

https://www.bilibili.com/video/av96166240/

End

本文分享自微信公众号 - 编程学习基地(LearnBase)

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2021-01-12

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 如何写出优雅的 Golang 代码

    原文: https://draveness.me/golang-101.html

    sunsky
  • Android开发如何写出优雅的代码

    很多时候我们去面试,人家总会问一个问题,你们公司开发一个app是如何进行技术选择的,app中涉及到了哪些开发模式,谈谈你对mvc、mvp和mvvm的区别。或许在...

    xiangzhihong
  • 如何写出优雅又地道的Python代码?

    译序 如果说优雅也有缺点的话,那就是你需要艰巨的工作才能得到它,需要良好的教育才能欣赏它。 —— Edsger Wybe Dijkstra 在Python社...

    小小科
  • 如何优雅的写好Pythonic代码?

    Python 与其它语言(比如Java或者C++)相比有比较大的区别,其中最大的特点就是非常简洁。如果按照其它语言的思路来写Python代码,则会使得代码繁琐复...

    测试小兵
  • 如何写出优雅的 JS 代码?使用 SOLID 原则

    把这六个原则的首字母联合起来(两个 L 算做一个)就是 SOLID (solid,稳定的),其代表的含义就是这六个原则结合使用的好处:建立稳定、灵活、健壮的设计...

    前端小智@大迁世界
  • 如何更优雅的编写CSS代码

    直白的说:编写优秀的 css 代码可能是很痛苦的。很多程序员都不想从事 CSS 开发—我可以做任何事情,除了css以外。

    icepy
  • 如何写出优秀的代码

    写了太多屎一样的代码,终于不臭了!更多精彩文章请关注公众号『Pythonnote』或者『全栈技术精选』

    小闫同学啊
  • 【专业技术】如何写出优美的C 代码?

    面向对象的语言更接近人的思维方式,而且在很大程度上降低了代码的复杂性,同时提高了代码的可读性和可维护性,传统的 C 代码同样可以设计出比较易读,易维护,复杂度较...

    程序员互动联盟
  • 如何写出优雅的 JS 代码,变量和函数的正确写法

    在开发中,变量名,函数名一般要做到清晰明了,尽量做到看名字就能让人知道你的意图,所以变量和函数命名是挺重要,今天来看看如果较优雅的方式给变量和函数命名。

    前端小智@大迁世界

扫码关注云+社区

领取腾讯云代金券