Google C++编程风格指南

0. 背景


  每一个C++程序员都知道,C++具有很多强大的语言特性,但这种强大不可避免的导致它的复杂,这种复杂会使得代码更易于出现bug、难于阅读和维护。

  本指南的目的是通过详细阐述在C++编码时要怎样写、不要怎样写来规避其复杂性。这些规则可在允许代码有效使用C++语言特性的同时使其易于管理。

1. 头文件


1.1 #define保护

  • 目的:防止头文件被多重包含
  • 原型:
#ifndef  XXX_XXX_H
#define XXX_XXX_H
...
#endif //XXX_XXX_H

1.2 能依赖声明的就不要依赖定义

  使用前置声明,尽量少.h文件中#include的数量,防止依赖

1.3 内联函数

  • 只有当函数少于10行甚至更少时,才定义为内联函数
  • 函数声明为内联,编译器直接在调用处展开代码,节省成本
  • 析构函数不应该内联,析构函数往往比其表面看起来要长
  • 不要内联那些包含循环、switch语句的函数
    • 除非大多数情况下,循环和switch从不执行
  • 虚函数和递归函数即使被声明为内联函数,实际上他不一定被执行

1.4 函数参数顺序

  • 输入参数在前,输出参数在后
  • 输入参数一般为:值 或 常数引用
  • 输出参数一般为: 非常数指针
  • 好处:
    • 提高可读性和易维护性
    • 对函数参数的堆栈空间有轻微影响

1.5 包含文件的次序

  C库 > C++库 > 其他库的h > 项目内的h

2. 作用域


2.1 命名空间

2.1.1 定义

  • 将全局作用域分为不同的、具名的作用域
  • 防止全局作用域命名冲突

2.1.2 优点

  • 提供了可嵌套的命名轴线
  • 命名轴线功能距离
    • project1 : : Foo
    • project2 : : Foo

2.1.3 缺点

  在头文件中使用不具名的空间容易违背C++的唯一定义原则

2.1.4 结论:根据上下文合理使用命名空间

  • .cc文件允许甚至提倡不具名命名空间

    • .cc文件包含更多、更复杂的细节
    • 有对其他命名空间中类的引用
  • .h不要使用不具名命名空间

2.2 嵌套类

  • 不要把嵌套类定义为public,除非他们是接口的一部分
  • 最好将嵌套类的声明置于命名空间中

2.3 非成员函数 / 静态成员函数 / 全局函数

  • 使用命名空间中的非成员函数/静态成员函数
  • 尽量不使用全局函数
  • 更好的方法是:将非、静作为新类的成员
  • 如果单纯为了封装,将不相干的函数放在一起,那还是用命名空间

2.4 局部变量

  • 尽可能置于最小作用域,最好声明变量时就初始化
  • 声明与第一次使用位置越近越好
  • for(int i = 0; i < 10; ++i)
    • gcc可正确执行,其他for循环重用第一次循环定义的i

2.5 全局变量

  • class类型全局变量是被禁止的
  • 内置类型的全局变量是允许的,但使用要三思
  • 多线程代码中非常数全局变量也是被禁止的

3. C++类


3.1 构造函数的职责

  • 职责:只进行没有实际意义的初始化
  • 有意义的数据用init方法实现
  • 缺点:
    • 不易捕获错误,不能使用异常
    • 操作失败会造成对象初始化失败,引起不确定状态
  • 对单参数的构造函数使用C++关键字explicit
    • 单参数构造函数必须是明确的
    • 拷贝构造函数大多数情况也要声明explicit

      例外:特意作为其它类的透明包装器的类
    • 禁止使用拷贝构造函数和赋值操作的宏

3.2 结构体和类

  仅当只有数据时使用struct,其他一概使用class

3.3 继承

  • 使用组合通常比使用继承更适宜
  • 如果使用继承,只使用公共继承
  • 所有继承必须是public,想私有继承的话,应采取包含基类实例的方式替代
  • 如果该类有虚函数,其析构函数也应该为虚函数
  • 派生类重定义基类的虚函数时,该派生类函数夜莺声明为virtual函数

3.4 多重继承

  • 应用场景:

      只有至多一个基类中含有实现,其他基类都是纯接口类
  • 优点:

      相比单继承,可复用更多代码

3.5 接口

  • 需满足的条件:

    • 只有纯虚函数和静态函数
    • 没有非静态成员函数
    • 没有定义任何构造函数
  • 必须为之声明虚析构函数
    • 确保接口的所有实现可被正确销毁
    • 此时,该虚析构函数亦为纯虚函数

3.6 操作符重载

  一般情况下不要重载操作符

3.7 存取控制

  • 即get/set函数
  • 存取函数一般内联在头文件中

3.8 Summary

  • 不在构造函数中做太多与逻辑相关的初始化
  • 编译器默认提供的构造函数不会对变量进行初始化
  • 子类重载的虚函数也要声明virtual关键字

4. 智能指针和其他C++特性


  • 智能指针安全第一,方便第二,尽可能局部化

    • 一般用scoped_ptr
    • 任何情况下不用auto_ptr
    • 对stl容器对象,使用shared_ptr
  • 引用形参加上const,否则使用指针形参
    • 避免丑代码:(*ptr)++
    • 对于拷贝构造函数,const是必须的
  • 函数重载的使用要清晰/易读
  • 少用缺省函数参数
  • 禁止使用变长数组和alloca
  • 合理使用友元
  • 慎用异常
  • 使用C++风格的类型转换,除单元测试外不要使用dynamic_cast
  • 能用前置自增/减,不用后置自增/减
    • 前置自增效率更高,后置自增自减要对变量值i进行依次拷贝
    • 如果i是迭代器或者其他非数值类型,一定要用前置
  • const能用则用,提倡const在前
    • const变量/函数/参数,会为编译时类型检测增加了一层保障
  • 尽量避免使用宏(c++中)
    • 尽量以内联函数、枚举、常量代替之
    • 不要在头文件中定义宏
  • 整数用0,实数0.0,指正NULL,字符串‘\0’
  • 推荐用sizeof(varname)代替sizeof(type)
  • 只使用Boost中被认可的库

5. 命名约定

  • 不要随意缩写,除非常用约定俗成的缩写
  • 函数名可适当为动词,其他命名使用名词
  • 全部大写+下划线: 宏/枚举
  • 全小写+下划线: 变量(含类变量/结构体变量)、文件、命名空间、存取函数
  • 大小写混合: 函数/类型(类/结构体/枚举)/常量

6.思维导图笔记



大图

读书笔记 |Google C++编程风格指南的更多相关文章

  1. Java学习笔记(四)——google java编程风格指南(上)

    [前面的话] 年后开始正式上班,计划着想做很多事情,但是总会有这样那样的打扰,不知道是自己要求太高还是自我的奋斗意识不够?接下来好好加油.好好学学技术,好好学习英语,好好学习做点自己喜欢的事情,趁着自 ...

  2. Java学习笔记(五)——google java编程风格指南(中)

    [前面的话] 年后开始正式上班,计划着想做很多事情,但是总会有这样那样的打扰,不知道是自己要求太高还是自我的奋斗意识不够?接下来好好加油.好好学学技术,好好学习英语,好好学习做点自己喜欢的事情,趁着自 ...

  3. Java学习笔记(六)——google java编程风格指南(下)

    [前面的话] 年后开始正式上班,计划着想做很多事情,但是总会有这样那样的打扰,不知道是自己要求太高还是自我的奋斗意识不够?接下来好好加油.好好学学技术,好好学习英语,好好学习做点自己喜欢的事情,趁着自 ...

  4. Google C++编程风格指南 - 中文版

    Google C++编程风格指南 - 中文版 from http://code.google.com/p/google-styleguide/ 版本: 3.133原作者: Benjy Weinberg ...

  5. google C++编程风格指南之头文件的包括顺序

    google C++编程风格对头文件的包括顺序作出例如以下指示: (1)为了加强可读性和避免隐含依赖,应使用以下的顺序:C标准库.C++标准库.其他库的头文件.你自己project的头文件.只是这里最 ...

  6. Google Java编程风格指南

    出处:http://hawstein.com/posts/google-java-style.html 声明:本文采用以下协议进行授权: 自由转载-非商用-非衍生-保持署名|Creative Comm ...

  7. Google Java编程风格指南中文版

    作者:Hawstein出处:http://hawstein.com/posts/google-java-style.html声明:本文采用以下协议进行授权: 自由转载-非商用-非衍生-保持署名|Cre ...

  8. Google C++编程风格指南

    作者:Hawstein 出处:http://hawstein.com/posts/google-cpp-style-guide.html 前言 越来越发现一致的编程风格的重要性,于是把Google的C ...

  9. Google Java 编程风格指南 —— 见微知著

    目录 前言 源文件基础 源文件结构 格式 命名约定 编程实践 Javadoc 后记 前言 这份文档是Google Java编程风格规范的完整定义.当且仅当一个Java源文件符合此文档中的规则, 我们才 ...

随机推荐

  1. perl 定义post接口

    [root@wx03 mojo]# cat a1.pl use Digest::MD5; my $md5 = Digest::MD5->new; $md5->add(1234567); p ...

  2. 【HDOJ】2896 病毒侵袭

    AC自动机模板题. #include <iostream> #include <cstdio> #include <cstring> #include <qu ...

  3. (转载)PHP常用函数

    (转载)http://www.cnblogs.com/dreamhome/archive/2011/05/04/2037011.html <?php //==================== ...

  4. 【图论】Codeforces 711D Directed Roads

    题目链接: http://codeforces.com/problemset/problem/711/D 题目大意: 给一张N个点N条有向边的图,边可以逆向.问任意逆向若干条边使得这张图无环的方案数( ...

  5. HDOJ(HDU) 2137 circumgyrate the string(此题用Java-AC不过!坑)

    此题如果有用JavaACDSee,请评论,谢谢了. Problem Description Give you a string, just circumgyrate. The number N mea ...

  6. FreeMarker-TemplateLoader

    Java中不乏优秀的模板引擎,Velocity,mvel,FreeMarker等.在构建框架的时候,通常可以拿来即用,但我们需要控制它.最近需要一个数据准备的框架,便选择了FreeMarker,Fre ...

  7. 《Mathematical Olympiad——组合数学》——染色问题

    恢复  继续关于<Mathematical Olympiad——组合数学>中问题的分析,这一篇文章将介绍有关染色的问题. 问题一: 将一些石头放入10行14列的矩形方格表内,允许在每个单元 ...

  8. Dolls - 4160(简单二分图匹配)

    题意:有一些箱子,大箱子可以套小箱子,但是必须h>h,w>w,l>l,求出来最外面能剩下几个箱子无法被嵌套.   分析:思考每个箱子都只会被别的箱子套一次,所以构成一二分匹配模型,只 ...

  9. bzoj3669: [Noi2014]魔法森林 lct

    记得去年模拟赛的时候好像YY出二分答案枚举a,b的暴力,过了55欸 然后看正解,为了将两维变成一维,将a排序,模拟Kruskal的加边过程,同时维护1到n的最大值,加入一条边e(u,v,a,b)时有以 ...

  10. PreTranslateMessage作用和用法

    PreTranslateMessage作用和用法  PreTranslateMessage是消息在送给TranslateMessage函数之前被调用的,绝大多数本窗体的消息都要通过这里,比較经常使用, ...