google 代码风格笔记

google 代码风格笔记

yolocai 2017.8.3javascript

1. 全部按引用传递的参数必须加上 const.

`void Foo(const string &in, string *out);`

2. 函数重载

若是您打算重载一个函数, 能够试试改在函数名里加上参数信息。例如,用 AppendString() 和 AppendInt() 等, 而不是一口气重载多个 Append().java

3. 不一样整形和无符号数据类型

4. 使用宏时要很是谨慎, 尽可能之内联函数, 枚举和常量代替之.

值得庆幸的是, C++ 中, 宏不像在 C 中那么必不可少. 以往用宏展开性能关键的代码, 如今能够用内联函数替代. 用宏表示常量可被 const 变量代替. 用宏 “缩写” 长变量名可被引用代替. 用宏进行条件编译… 这个, 千万别这么作, 会令测试更加痛苦 (#define 防止头文件重包含固然是个特例).web

下面给出的用法模式能够避免使用宏带来的问题; 若是你要宏, 尽量遵照:
+ 不要在 .h 文件中定义宏.
+ 在立刻要使用时才进行 #define, 使用后要当即 #undef.
+ 不要只是对已经存在的宏使用#undef,选择一个不会冲突的名称;
+ 不要试图使用展开后会致使 C++ 构造不稳定的宏, 否则也至少要附上文档说明其行为.
+ 不要用 ## 处理函数,类和变量的名字。ide

5. 你能够用列表初始化。

```
// Vector 接收了一个初始化列表。
vector<string> v{"foo", "bar"};

// 不考虑细节上的微妙差异,大体上相同。
// 您能够任选其一。
vector<string> v = {"foo", "bar"};

// 能够配合 new 一块儿用。
auto p = new vector<string>{"foo", "bar"};

// map 接收了一些 pair, 列表初始化大显神威。
map<int, string> m = {{1, "one"}, {2, "2"}};

// 初始化列表也能够用在返回类型上的隐式转换。
vector<int> test_function() { return {1, 2, 3}; }

// 初始化列表可迭代。
for (int i : {-1, -2, -3}) {}

// 在函数调用里用列表初始化。
void TestFunction2(vector<int> v) {}
TestFunction2({1, 2, 3});
```

6. 只有当函数只有 10 行甚至更少时才将其定义为内联函数.

7. #include 的路径及顺序

使用标准的头文件包含顺序可加强可读性, 避免隐藏依赖: 相关头文件, C 库, C++ 库, 其余库的 .h, 本项目内的 .h.svg

8. 将函数变量尽量置于最小做用域内, 并在变量声明时进行初始化.

int i;
i = f(); // 坏——初始化和声明分离
int j = g(); // 好——初始化时声明

vector<int> v;
v.push_back(1); // 用花括号初始化更好
v.push_back(2);

vector<int> v = {1, 2}; // 好——v 一开始就初始化

若是变量是一个对象, 每次进入做用域都要调用其构造函数, 每次退出做用域都要调用其析构函数.函数

// 低效的实现
for (int i = 0; i < 1000000; ++i) {
    Foo f;                  // 构造函数和析构函数分别调用 1000000 次!
    f.DoSomething(i);
}

Foo f;                      // 构造函数和析构函数只调用 1 次
for (int i = 0; i < 1000000; ++i) {
    f.DoSomething(i);
}

9. 隐式类型转换

不要定义隐式类型转换. 对于转换运算符和单参数构造函数, 请使用 explicit 关键字.性能

class String{
    public:
    explicit String(int n){};
    String(const char *p){};
};

void Func(Foo f){};
int main(){
     //String s1 = 'a'; //错误:不能作隐式char->String转换
    String s2(10);   //能够:调用explicit String(int n);
    String s3 = String(10);//能够:调用explicit String(int n);再调用默认的复制构造函数
    String s4 = "Brian"; //能够:隐式转换调用String(const char *p);再调用默认的复制构造函数
    String s5("Fawlty"); //能够:正常调用String(const char *p);
}

10. 结构体 VS. 类

仅当只有数据成员时使用 struct, 其它一律使用 class.测试

11. 继承

全部继承必须是 public 的. 若是你想使用私有继承, 你应该替换成把基类的实例做为成员对象的方式.ui

不要过分使用实现继承. 组合经常更合适一些. 尽可能作到只在 “是一个” (“is-a”, 其余 “has-a” 状况下请使用组合) 的状况下使用继承: 若是 Bar 的确 “是一种” Foo, Bar 才能继承 Foo.google

必要的话, 析构函数声明为 virtual. 若是你的类有虚函数, 则析构函数也应该为虚函数.

对于可能被子类访问的成员函数, 不要过分使用 protected 关键字. 注意, 数据成员都必须是 私有的.

对于重载的虚函数或虚析构函数, 使用 override, 或 (较不经常使用的) final 关键字显式地进行标记. 较早 (早于 C++11) 的代码可能会使用 virtual 关键字做为不得已的选项. 所以, 在声明重载时, 请使用 override, final 或 virtual 的其中之一进行标记. 标记为 override 或 final 的析构函数若是不是对基类虚函数的重载的话, 编译会报错, 这有助于捕获常见的错误. 这些标记起到了文档的做用, 由于若是省略这些关键字, 代码阅读者不得不检查全部父类, 以判断该函数是不是虚函数.

12. 声明顺序

类定义通常应以 public: 开始, 后跟 protected:, 最后是 private:. 省略空部分.

13. 参数顺序

函数的参数顺序为: 输入参数在先, 后跟输出参数.

14. 命名规则

通用命名规则

int price_count_reader;    // 无缩写
int num_errors;            // "num" 是一个常见的写法
int num_dns_connections;   // 人人都知道 "DNS" 是什么
int n;                     // 毫无心义.
int nerr;                  // 含糊不清的缩写.
int n_comp_conns;          // 含糊不清的缩写.
int wgc_connections;       // 只有贵团队知道是什么意思.
int pc_reader;             // "pc" 有太多可能的解释了.
int cstmr_id;              // 删减了若干字母.

文件命名

文件名要所有小写, 能够包含下划线 () 或连字符 (-), 依照项目的约定. 若是没有约定, 那么 “” 更好.

类型命名

类型名称的每一个单词首字母均大写, 不包含下划线: MyExcitingClass, MyExcitingEnum.

变量命名

变量 (包括函数参数) 和数据成员名一概小写, 单词之间用下划线链接. 类的成员变量如下划线结尾, 但结构体的就不用, 如: a_local_variable, a_struct_data_member, a_class_data_member_.

函数命名

常规函数使用大小写混合, 取值和设值函数则要求与变量名匹配: MyExcitingFunction(), MyExcitingMethod(), my_exciting_member_variable(), set_my_exciting_member_variable().