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. Delphi 的运算符列表,运算符及优先级表格 good

    Delphi 的运算符列表 分类 运算符 操作 操作数 结果类型 范例 算术运算符 + 加 整数,实数 整数,实数 X + Y - 减 整数,实数 整数,实数 Result - 1 * 乘 整数,实数 ...

  2. 【HDOJ】3329 The Flood

    超简单BFS. /* 3329 */ #include <iostream> #include <queue> #include <cstdio> #include ...

  3. 【HDOJ】4704 Sum

    数学题.f(n) = 2^(n-1) mod (1e9+7). #include <cstdio> #define MAXN 100005 char buf[MAXN]; __int64 ...

  4. 【转】Android4.3 蓝牙BLE初步

    原文网址:http://www.cnblogs.com/savagemorgan/p/3722657.html 一.关键概念: Generic Attribute Profile (GATT) 通过B ...

  5. Xmanager4使用记录

    想在windows下远程登录到了Linux桌面,但又不想装vnc server,况且根据同学的实践,vnc的桌面在远程和本地都能看得到,这个似乎不太好.   google到xmanager,装了个测试 ...

  6. 数学(快速数论变换):SDOI2015 序列统计

    [题目描述] 小C有一个集合S,里面的元素都是小于M的非负整数.他用程序编写了一个数列生成器,可以生成一个长度为N的数列,数列中的每个数都属于集合S. 小C用这个生成器生成了许多这样的数列.但是小C有 ...

  7. 解决wordpress的fonts.googleapis.com在国内无法访问的问题

    因为wordpress及主题的样式中几乎都使用了fonts.googleapis.com,而国内因为你知道的原因,是无法正常使用google服务的,因此导致在很多国内设备上打不开wordpress页面 ...

  8. Android开发必知--自定义Toast提示

    开发过Android的童鞋都会遇到一个问题,就是在打印Toast提示时,如果短时间内触发多个提示,就会造成Toast不停的重复出现,直到被触发的Toast全部显示完为止.这虽然不是什么大毛病,但在用户 ...

  9. 最长回文 HDU 3068 (裸的Manacher)

    直接看代码: ============================================================================================= ...

  10. Blue Jeans - POJ 3080(多串的共同子串)

    题目大意:有M个串,每个串的长度都是60,查找这M个串的最长公共子串(连续的),长度不能小于3,如果同等长度的有多个输出字典序最小的那个.   分析:因为串不多,而且比较短,所致直接暴力枚举的第一个串 ...