GoogleCpp风格指南 8)格式 _part2

8.9 布尔表达式 Boolean Expressions

Tip 如果一个布尔表达式超过标准行宽standard line length; 断行方式要统一一下;

下例中, 逻辑与(&&)操作符总位于行尾:


1

2

3

4

5

if (this_one_thing
> this_other_thing &&

    a_third_thing
== a_fourth_thing &&

    yet_another
& last_one) {

  ...

}

注意, 上例的逻辑与AND (&&)操作符均位于行尾; Google风格是这样的; 如果是在每行前加上操作符也是允许的; 可以考虑额外插入圆括号, 合理使用的话对增强可读性是很有帮助的;

[Add] 应该总是使用标点punctuation操作符, 如 &&和~ [按位取反], 而不是字符操作符, 如 and和cmpl; <<<

8.10 函数返回值 Return Values

Tip return表达式express中不要用圆括号包围;

函数返回时不要使用圆括号, 除了在 int x = expr 中会使用; [返回表达式]


1

return x;  //
not return(x);

只有在类似这种情况下对retrun表达式使用圆括号: 当你在 int x = expr; 中会使用圆括号的话;


1

2

3

4

return result;                  //
No parentheses in the simple case.

// Parentheses OK to make a complex expression
more readable.

return (some_long_condition
&&

        another_condition);

WARNING:


1

2

return (value);                //
You wouldn‘t write var = (value);

return(result);                //
return is not a function!

8.11 变量及数组初始化 Variable and Array Initialization

Tip 用 = 或 () 都可以; [Add] or {}.
<<<;

从中做出选择: 下面的方式都是正确的:


1

2

3

4

5

6

int x
= 3;

int x(3);

string name("Some
Name"
);

string name = "Some
Name"
;

//[Add]

string name{"Some
Name"
};

[Add]

对一个std::initializer_list ctor的类型使用braced initialization list {...}时要小心; 非空的nonempty braced-init-list建议尽量使用std::initializer_list ctor; 注意空的empty braces {}是特殊的, 可能的情况下会调用一个默认ctor; 要强制使用non-std::initializer_list
ctor, 使用圆括号代替花括号;


1

2

vector<int>
v(100, 1);  
//
A vector of 100 1s. 100个1

vector<int>
v{100, 1};  
//
A vector of 100, 1.

同时, brace形式还可以防止整型收缩问题narrowing of integral types; 可以防止一些编程错误


1

2

int pi(3.14);  //
OK -- pi == 3.

int pi{3.14};  //
Compile error: narrowing conversion.

<<<

8.12 预处理指令 Preprocessor Directives

Tip 预处理指令不要缩进, 从行首开始: (hash mark)

即使预处理指令位于缩进代码块中, 指令也应从行首开始;


1

2

3

4

5

6

7

8

9

10

// Good - directives at beginning of line

  if (lopsided_score)
{

#if DISASTER_PENDING      // Correct -- Starts at beginning
of line

    DropEverything();

# if NOTIFY               // OK but not required --
Spaces after #

    NotifyClient();

# endif

#endif

    BackToNormal();

  }

WARNING


1

2

3

4

5

6

7

// Bad - indented directives

  if (lopsided_score)
{

    #if
DISASTER_PENDING  // Wrong!  The "#if" should be at beginning of line

    DropEverything();

    #endif               
// Wrong!  Do not indent "#endif"

    BackToNormal();

  }

8.13 类格式 Class Format

Tip 访问控制块的声明依次序是 public, protected, private, 每次缩进一个空格; [默认是没有缩进的]

类声明(对类注释不了解的话, 参考--类注释Class Comments)的基本格式如下:


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

class MyClass
public OtherClass
{

 public:      //
Note the 1 space indent!

  MyClass();  //
Regular 2 space indent.

  explicit MyClass(int var);

  ~MyClass()
{}

  void SomeFunction();

  void SomeFunctionThatDoesNothing()
{

  }

  void set_some_var(int var)
{ some_var_ = var; }

  int some_var() const return some_var_;
}

 private:

  bool SomeInternalFunction();

  int some_var_;

  int some_other_var_;

  DISALLOW_COPY_AND_ASSIGN(MyClass);

};

注意事项:

- 所有基类名应该在80列限制下尽量与子类名放在同一行; (80字符行宽)

- 关键词 public, protected, private要缩进1个空格;

- 除第一个关键词(一般是public)外, 其他关键词要在前面preceded空一行; 如果类比较小的话也可以不空;

- 这些关键词后不要保留空行;

- public放在最前面, 然后是protected, 最后是private;

- 关于声明顺序的规程参考--声明顺序Declaration Order;

8.14 初始化列表 Constructor Initializer Lists

Tip 构造函数初始化列表Constructor initializer lists放在同一行或按四格缩进并排几行;

下面两种初始化列表方式都可以接受;


1

2

// When it all fits on one line:

MyClass::MyClass(int var)
: some_var_(var), some_other_var_(var + 1) {}


1

2

3

4

5

6

7

8

9

// When it requires multiple lines, indent
4 spaces, putting the colon on

// the first initializer line:

MyClass::MyClass(int var)

    :
some_var_(var),             
//
4 space indent

      some_other_var_(var
+ 1) {  
//
lined up

  ...

  DoSomething();

  ...

}

[有些风格喜欢在初始化列表中, 将逗号写在前面, 那样编辑起来方便点]

8.15 名字空间格式化 Namespace Formatting

Tip 名字空间内容不缩进;

名字空间不要增加额外的缩进层次; 例如:


1

2

3

4

5

6

7

namespace {

void foo()
{  
//
Correct.  No extra indentation within namespace.

  ...

}

}  //
namespace

不要缩进名字空间;

WARNING:


1

2

3

4

5

6

7

8

namespace {

  //
Wrong.  Indented when it should not be.

  void foo()
{

    ...

  }

}  //
namespace

[Add]

在声明嵌套的名字空间时, 把每个名字空间都放在自己独立的行中;


1

2

namespace foo
{

namespace bar
{

<<<

8.16 水平留白 Horizontal Whitespace

Tip 水平留白的使用因地制宜, 永远不要在行尾添加无意义的留白;

常规: General


1

2

3

4

5

6

7

8

9

10

11

12

13

14

void f(bool b)
{  
//
Open braces should always have a space before them.

  ...

int i
= 0;  
//
Semicolons usually have no space before them.

int x[]
= { 0 };  
//
Spaces inside braces for array initialization are

int x[]
= {0};    
//
optional.  If you use them, put them on both sides!

// Spaces around the colon in inheritance and
initializer lists.

class Foo
public Bar
{

 public:

  //
For inline function implementations, put spaces between the braces

  //
and the implementation itself.

  Foo(int b)
: Bar(), baz_(b) {}  
//
No spaces inside empty braces.

  void Reset()
{ baz_ = 0; }  
//
Spaces separating braces from implementation.

  ...

添加冗余的留白会给其他人在编辑merge时造成额外负担; 因此行尾不要留空格; 如果确定一行代码已经修改完毕, 将多余的空格去掉; 或者在专门清理空格时去掉(确信没有其他人在处理); (译注: 现在大部分代码编辑器稍加设置后, 都支持自动删除行首/尾空格; 如果不支持, 考虑换一款编辑器或IDE);

循环和条件语句: Loops and Conditionals


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

if (b)
{          
//
Space after the keyword in conditions and loops.

else {          //
Spaces around else.

}

while (test)
{}   
//
There is usually no space inside parentheses.

switch (i)
{

for (int i
= 0; i < 5; ++i) {

switch (
i ) {    
//
Loops and conditions may have spaces inside

if (
test ) {     
//
parentheses, but this is rare.  Be consistent.

for int i
= 0; i < 5; ++i ) {

for (
; i < 5 ; ++i) {  
//
For loops always have a space after the

  ...                   //
semicolon, and may have a space before the

                        //
semicolon.

switch (i)
{

  case 1:         //
No space before colon in a switch case.

    ...

  case 2: break;  //
Use a space after a colon if there‘s code after it.

[Add]


1

2

3

4

// Range-based for loops always have a space
before and after the colon.

for (auto x
: counts) {

  ...

}

<<<

操作符 Operators


1

2

3

4

5

6

7

8

9

x = 0;              //
Assignment operators always have spaces around

                    //
them.

x = -5;             //
No spaces separating unary operators and their

++x;                //
arguments.

if (x
&& !y)

  ...

v = w * x + y / z;  //
Binary operators usually have spaces around them,

v = w*x + y/z;      //
but it‘s okay to remove spaces around factors.

v = w * (x + z);    //
Parentheses should have no spaces inside them(internal padding)

[Add]


1

2

3

4

// No spaces separating unary operators and
their arguments.

x = -5;

++x;

if (x
&& !y)

<<<

模板和转换: Templates and Casts


1

2

3

4

5

6

7

8

9

10

11

12

// No spaces inside the angle brackets (< and
>), before

// <, or between >( in a cast

vector<string> x;

y = static_cast<char*>(x);

// Spaces between type and pointer are OK,
but be consistent.

vector<char *>
x;

set<list<string>> x;        //
Permitted in C++11 code.

set<list<string> > x;       //
C++03 required a space in > >.

// You may optionally use symmetric spacing
in < <.

set< list<string> > x;

8.17 垂直留白 Vertical Whitespace

Tip 垂直留白越少越好

这不仅仅是规则而是原则问题了: 不在万不得已, 不要使用空行, 尤其是: 两个函数定义之间的空行不要超过2行; 函数体首尾不要超过2行; 函数体首位不要留空行, 函数体中也不要随意添加空行;

基本原则是: 同一屏可以显示的代码越多, 越容易理解程序的控制流; 当然, 过于密集dense的代码块和过于疏松的代码块同样难看; 取决于你的判断; 但通常是垂直留白越少越好;

[Remove]

WARNING 函数首尾不要有空行;


1

2

3

4

5

void Function()
{

  //
Unnecessary blank lines before and after

}

WARNING 代码块首尾不要有空行;


1

2

3

4

5

6

7

8

while (condition)
{

  //
Unnecessary blank line after

}

if (condition)
{

  //
Unnecessary blank line before

}

if-else块之间空一行是可以接受的;


1

2

3

4

5

6

7

if (condition)
{

  //
Some lines of code too small to move to another function,

  //
followed by a blank line.

else {

  //
Another block of code

}

<<<

[Add]

一些关于空行的经验准则rules of thumb:

- 在函数的头尾处的空行可读性不佳;

- 在一系列 if-else块中的空行有助于可读性;

<<<

译者笔记

0) 对于代码格式, 因系统各异有优缺点, 但同一个项目中遵循同一标准还是有必要的;

1) 行宽原则上不超过80列, 把22寸的显示器也占完了; [分辨率到底是有多低...]

2) 尽量不使用非ASCII字符; 如果使用的话, 参考UTF-8格式(尤其是 UNIX/Linux下, Windows下可以考虑宽字符); 尽量不将字符串常量耦合到代码中, 比如独立出资源文件, 这不仅仅是风格问题;

3) UNIX/Linux下无条件使用空格; MSVC的话使用Tab也无可厚非; [用Tab会把code review diff弄成渣]

4) 函数参数, 逻辑条件, 初始化列表: 要么所有参数和函数名放在同一行, 要么所有参数并排分行;

5) 除函数定义的左大括号可以置于行首外, 包括函数/类/结构体/枚举声明, 各种语句的左大括号置于行尾, 所有右大括号独立成行;

6) ./->操作符前后不留空格, */&不要前后都留, 一个即可, 靠左靠右依照个人喜好; [统一一下]

7) 预处理指令/命名空间不使用额外缩进, 类/结构体/枚举/函数/语句使用缩进;

8) 初始化用 = 还是 () 依照个人喜好, 统一即可;

9) return 不要加 ();

10) 水平/垂直留白不要滥用, 怎么易读怎么来;

11) 关于UNIX/Linux风格为什么要把左大括号置于行尾(.cc文件的函数实现处, 左大括号位于行首); 我的理解是代码看上去比较简约;  行首除了函数体被一对大括号封在一起外, 只有右大括号的代码看上去比较舒服; Windows风格将做大括号置于行首的优点是匹配情况一目了然;

---YCR---

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-08-05 10:18:21

GoogleCpp风格指南 8)格式 _part2的相关文章

GoogleCpp风格指南 8)格式 _part1

8 格式 Formatting 代码风格和格式确实比较随意, 但一个项目中所有人遵循同一风格是非常容易的; 个体未必同意下述每一处格式规则, 但整个项目服从统一的编程风格是很重要的, 只有这样才能让所有人很轻松地阅读和理解代码; 我们写了一个 settings file for emacs [http://google-styleguide.googlecode.com/svn/trunk/google-c-style.el] 帮助你正确的格式化代码; 8.1 行长度 Line Length T

GoogleCpp风格指南 5) 其他特性_part1

5 其他C++特性 Other C++ Features 5.1 引用参数 Reference Arguments Tip 所有按引用传递的参数必须加上 const; 定义: 在C语言中, 如果函数需要修改变量的值, 参数必须为指针, 如 int foo(int* pval); 在C++中, 函数还可以声明引用参数 int foo(int& val); 优点: 定义引用参数防止出现 (*pval)++ 这样丑陋的代码; 像拷贝构造函数这样的应用也是必需的, 而且更明确, Note 不接受NULL

GoogleCpp风格指南 1)头文件 2)作用域

Google开源项目风格指南 v3.133 原作: Benjy Weinberger, Craig Silverstein, Gergory Eitzmann, Mark Mentovai, Tashana Landray 翻译: YuleFox, brantyoung 修改: YCR 0 扉页 0.1 译者前言 Google经常发布一些开源项目, 因此发布这份编程风格, 使所有提交代码的人能获知Google的编程风格; 规则的作用是避免混乱, 但规则本身要权威, 有说服力, 并且是理性的, 大

GoogleCpp风格指南 5) 其他特性_part2

5.10 前置自增和自减 Preincrement and Predecrement Tip 对于迭代器iterator和其他模板对象template object使用前缀形式(++i)的自增, 自减运算符; 定义: 对于变量在自增(++i 或 i++)或自减(--i 或 i--)后, 表达式的值没有被用到的情况下, 需要确定到底是使用前置还是后置的自增(自减); 优点: 不考虑返回值的话, 前置pre自增(++i)通常要比后置post自增(i++)效率更高; 因为后置自增(自减)需要对表达式的

GoogleCpp风格指南 5) 其他特性_part3

[Add] Lambda expressions 在合适的时候使用lambda表达式; 不要使用默认的lambda captures, 使用显式的captures; [http://en.cppreference.com/w/cpp/language/lambda ] 定义: lambda表达式是一个创建匿名函数对象anonymous function objects.的简洁concise方式; 在将函数作为参数传递的时候很有用; 1 2 3 std::sort(v.begin(), v.end

GoogleCpp风格指南 7)注释

7 注释 Comments 注释虽然写起来很痛苦, 但对保证代码可读性至关重要; 下面的规则描述了如何注释以及在哪注释; 当然也要记住: 注释固然很重要, 但最好的代码本身应该是文档化self-documenting; 有意义的类型名和变量名, 要远胜过要用注释解释的含糊不清的名字; 你写的注释是给代码读者看的: 下一个需要理解你代码的人, 慷慨些吧, 下一个人可能就是你; 7.1 注释风格 Comment Style Tip 使用 // 或 /* */, 统一就好; // 或 /* */都可以

GoogleCpp风格指南 4)Google奇技

4 来自Google的奇技 Google-Specific Magic Google用了很多自己的实现技巧/工具使 C++代码更加健壮, 我们使用C++的方式可能和你在其他地方见到的有所不同; [Removed] 4.1 智能指针 Tip 如果确实需要使用智能指针的话, scoped_ptr完全可以胜任; 你应该只在非常特定的情况下使用 std::tr1::shared_ptr, 例如STL容器中的对象; 任何情况下都不要使用 auto_ptr; "智能"指针看上去是指针, 其实是附加

GoogleCpp风格指南 3)类

3 类 Classes 类是C++中代码的基本单元; 显然, 它们被广泛使用; 本节列举了写一个类时的主要注意事项; 3.1 构造函数的职责 Doing Work in Constructors Tip 构造函数中只进行那些没什么意义的(trivial 译注: 简单初始化对于程序执行没有实际的逻辑意义, 因为成员变量"有意义"的值大多不再构造函数中确定)初始化, 可能的话, 使用 Init()方法集中初始化有意义的(non-trival)数据; [Add] 在ctor中防止做复杂的初始

GoogleCpp风格指南 6)命名约定

6 命名约定 Naming 最重要的一致性规则是命名管理govern naming; 命名风格快速获取名字代表是什么: 类型? 变量, 函数, 常量, 宏, ...甚至不需要去查找类型声明; 大脑中的模式匹配引擎pattern-matching engine可以非常可靠的处理这些命名规则; 命名规则具有一定随意性, 但相比按个人喜好命名, 一致性更重要, 所以不管你怎么想, 规则总归是规则; 6.1 通用命名规则 General Naming Rules Tip 函数命名, 变量命名, 文件命名