开源项目风格指南》笔记"/>
C++格式规范,《google开源项目风格指南》笔记
//这是《google开源项目风格指南》C++版本的笔记,如果对其中内容感兴趣可以去找原书看。感谢作者和译者,救我小命。
C++特性
所有按引用传递的参数必须加上const
更推荐用printf+read/write instead of I/O流
对于迭代器和模板类型,使用前置自增自减
前提:c++中人们假定short是16位,Int 32位,long 32位,long long 64位。如果需要不同大小的整型变量,可以借助<stdint.h>中长度精确的整型,其中包括int16_t,uint_32_t,int64_t…其余问题不是老奴该关心的。
继承可以通过复用基类代码减少代码量
一般来说类的属性成员都应设置为private,public只留给外部调用的函数接口
头文件 扩展名为.h,包含C的函数声明和宏定义,有程序员编写的头文件和C标准库自带头文件,要使用头文件,需用预处理指令#include进行引用,饮用后可以使用头文件中声明的函数。
#include 预处理指令分两种,# include<> 引用系统头文件,#include "" 引用用户程序目录中的头文件,找不到去系统头文件里找。
内联函数 关键词 inline 放在函数定义前,可以将函数定义为内联函数,从而内联地展开,提升运行速度,但内联函数的语句一般不超过10行,超过就没必要内联了。如果内联包含循环/switch的函数,往往得不偿失。
//对于变量的声明/定义:声明是为了告诉编译器变量的类型和名称,而不申请存储空间,定义申请存储空间,可以赋初值,在C++中,二者区分不大,往往同时发生
对于函数的声明/定义:函数只要有实现(存在函数体 { …… } )即为定义,否则为声明。可以这样理解:函数声明是说明函数是什么,函数定义是说明函数做什么。
声明和定义的区别:
1.声明/定义次数_变量/函数可以声明多次,变量/函数的定义只能一次。
2.分配内存_声明不会分配内存,定义会分配内存。
3.做了什么_声明是告诉编译器变量或函数的类型和名称等,定义是告诉编译器变量的值,函数具体干什么。
C++允许函数在任何位置声明变量,将变量尽可能置于最小作用域内,而且相较于声明再赋值,最好一开始就初始化。
C++书写格式
每行代码字符数不超过80,尽量不要加空行
预处理指令永远从行首开始,不缩进,即使它处于缩进代码块中。
关于空格的不完全梳理
不使用制表位,需要有空格时输入空格,且每次缩进2个空格。
左大括号前总有空格,在列表初始化时大括号内的空格是optional,对于单行函数的实现,需要加空格。
分号前不加空格,循环内的分号后总有空格,且前面可以加一个空格。
赋值运算符前后总是有空格,其他二元操作符也是,不过表达式的子式可以不加空格。在参数和一元操作符之间不加空格。
switch case 的冒号前没有空格,如果后面有代码,冒号后加空格。
< >:“<”前无空格,内部也没有空格,“>”后的话,后跟(则无空格,跟变量有空格。
vector<string> x;
y = static_cast<char*>(x);
vector<char *> x; //可以在类型与指针操作符之间留空格哈
参数
在进行函数声明与定义时,返回类型和函数名放在同一行,如果放不下就对形参进行分行。在进行函数调用的时候同理。分行方式:
1.在括号内进行分行,参数应尽量对齐;
ReturnType ClassName::ReallyLongFunctionName(Type par_name1, Type par_name2,Type par_name3) {DoSomething();...
}
2.将参数另起一行,分行书写,且开头缩进四格;
ReturnType LongClassName::ReallyReallyReallyLongFunctionName(Type par_name1, // 4 space indentType par_name2,Type par_name3) {DoSomething(); // 2 space indent...
}
3.如果一系列参数本身就有一定的结构,可以酌情按其结构来决定参数格式;
my_widget.Transform(x1, x2, x3,y1, y2, y3,z1, z2, z3);
如果一些参数本身就是略复杂的表达式,且降低了可读性,可直接创建临时变量描述该表达式,并传递给函数。
int my_heuristic = scores[x] * y + bases[x];
bool retval = DoSomething(my_heuristic, x, y, z);
- 使用好的参数名.
- 只有在参数未被使用或者其用途非常明显时, 才能省略参数名.
- 如果返回类型和函数名在一行放不下, 分行.
- 如果返回类型与函数声明或定义分行了, 不要缩进.
- 左圆括号总是和函数名在同一行.
- 函数名和左圆括号间永远没有空格.
- 圆括号与参数间没有空格.
- 左大括号总在最后一个参数同一行的末尾处, 不另起新行.
- 右大括号总是单独位于函数最后一行, 或者与左大括号同一行.
- 右圆括号和左大括号间总是有一个空格.
- 所有形参应尽可能对齐.(像第一段代码那样)
- 缺省缩进为 2 个空格.
- 换行后的参数保持 4 个空格的缩进.
变量及数组初始化:有=/()/{}三种方式
int x = 3;
int x(3);
int x{3};
列表初始化:这个作者可文明了,他说“您平时怎么格式化函数调用,就怎么格式化列表初始化”。列表初始化中大括号内的空格可写可不写,如果加了,那么两边都要加上。{0}/{ 0 }都可
条件语句:在圆括号内不使用空格,圆括号外前后各一个空格,else与if的右括号同一行,当语句简单且没有使用else子句时,可以将条件语句直接写在同一行,否则达咩。通常单行语句不需要使用大括号,但想用也没人拦你。
开关选择语句:case可用大括号也可不用,如果有不满足 case
条件的枚举值, switch
应该总是包含一个 default
匹配 (如果有输入值没有 case 去处理, 编译器将给出 warning). 如果 default
应该永远执行不到, 简单的加条 assert
:
switch (var) {case 0: { // 2 空格缩进... // 4 空格缩进break;}case 1: {...break;}default: {assert(false);}
}
循环语句:单语句循环,括号可用可不用,空循环体应使用{}或continue
for (int i=0; i<kSomeNumber; ++i) {} //空循环体
while (contition) continue; continue表示没有逻辑
指针和引用表达式
在访问成员时,句点或箭头前后不要有空格,指针/地址操作符(*,&)之后不能有空格
foo = *p;
p = &x;
x = Boo.son;
x = Boo->son;
在声明指针变量或参数时,型号与类型或变量名紧挨都可以,是一样滴。
返回值:返回值又不是函数参数,不要加圆括号,除非为了将复杂表达式圈起来改善可读性
类:声明次序是public:,protected:,private:, 这三个关键词要缩进一个空格,其他语句正常缩2个空格。继承与初始化列表中的冒号前后永远有空格
构造函数初始值列表
还是和参数一样的原则,能一行排开就一行排开,排不开就换行/多行排,排得整齐点。
//能放同一行的话:
MyClass::MyClass(int var):some_var_(var) {FaireFaire();
}
//不能放同一行,先试试换行不跟声明定义放一块行不行:(tip:从冒号开始换行,并缩进4空格)
MyClass::MyClass(int var):some_var_(var),some_other_var_(var + 1) {FaireFaire();
}
//换行还不够用就拆开呗(注意对齐)
MyClass::MyClass(int var):some_var_(var),some_other_var_(var + 1) {FaireFaire();
}
命名约定
一些特定且广为人知的缩写是允许的,例如用i表示迭代变量,用T表示模板参数,尽量不要用一些除了你没几个人能懂什么意思的缩写。
文件命名:全部小写,可以包含_或-,一般_更好。C++文件要以结尾,头文件要以.h结尾,专门插入文本的文件则以.inc结尾。内联函数必须放在.h文件中。
类型命名:要以大写字母开始,每个单词首字母均大写,不包含下划线。包含类、结构体、类型定义(typedef)、枚举,类型模板参数等。
变量/数据成员命名:一律小写,单词间可用下划线连接,类的成员变量以下划线结尾,结构体的数据成员不用。
常量命名:声明为constexpr/const的变量,命名时以”k"开头,大小写混合。所有具有静态存储类型的变量都应以此方式命名。
eg. const int kDaysInAWeek = 7;
函数命名:一般使用驼峰变量名(就是前面说的开头大写啦),无下划线,首字母缩写构成的单词一般倾向于视为一个单词进行首字母大写 eg.StartRpc() instead of StartRPC()
枚举命名:kEnumName ENUM_NAME,最好优先选择常量风格的命名方式。
宏命名
嗯嗯嗯你说得对
更多推荐
C++格式规范,《google开源项目风格指南》笔记
发布评论