Samxander's home

You shall see the difference now that we are back again!

0%

Google开源项目风格指南精简版

自给自足的头文件

头文件应该可以独立编译,并以 .h 为拓展名。给需要被导入但不属于头文件的文件设置为 .inc 拓展名,并尽量避免使用。

#define防护符

所有头文件都应该用 #define 防护符来防止重复导入。防护符的格式是 <项目>_<路径>_<文件名>_H_ .

内联函数

只把 10 行以下的小函数定义为内联(inline).

1
2
3
inline int add(int a, int b) {
return a + b;
}

#include的路径及顺序

推荐按照以下顺序导入头文件:配套的头文件,C语言系统库头文件,C++标准库头文件,其他库的头文件,本项目的头文件。

举例来说, google-awesome-project/src/foo/internal/fooserver.cc 的导入语句如下:

1
2
3
4
5
6
7
8
9
10
11
#include "foo/server/fooserver.h"

#include <sys/types.h>
#include <unistd.h>

#include <string>
#include <vector>

#include "base/basictypes.h"
#include "foo/server/bar.h"
#include "third_party/absl/flags/flag.h"

命名空间

除了少数特殊情况,应该在命名空间 (namespace) 内放置代码。命名空间应该有独一无二的名字,其中包含项目名称,也可以选择性地包含文件路径。禁止使用 using 指令 (例如 using namespace foo). 禁止使用内联 (inline) 命名空间。

1
2
3
4
5
6
7
8
9
namespace mynamespace {

class Myclass {
public:
...
void Foo();
};

}

局部变量

应该尽可能缩小函数变量的作用域 (scope),并在声明的同时初始化。

1
2
3
4
int i;
i = f(); // 不好:初始化和声明分离,

int i = f(); // 良好:声明时初始化。
1
2
3
4
5
6
int jobs = NumJobs();
// 更多代码...
f(jobs); // 不好:初始化和使用位置分离,

int jobs = NumJobs()
f(jobs); // 良好:初始化以后立即(或很快)使用。
1
2
3
4
5
vector<int> v;
v.push_back(1);
v.push_back(2); // 用花括号初始化更好,

vector<int> v = {1, 2}; // 良好:立即初始化 v.

通常应该在语句内声明用于 ifwhilefor 语句的变量,这样会把作用域限制在语句内。例如:

1
while (const char* p = strchr(str, '/')) str = p + 1;

需要注意的是,如果变量是一个对象,那么它每次进入作用域时会调用构造函数,每次退出作用域时都会调用析构函数。

1
2
3
4
5
6
7
8
9
10
// 低效的实现:
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);
}

未完待续

Insist on writing original high-quality articles. Your support is my biggest motivation.