Google C + + programming style guide: format

The code style and format are indeed quite random, but it is very easy for everyone in a project to follow the same style Individuals may not agree with each of the following format rules, but it is important that the whole project obey a unified programming style. Only in this way can everyone easily read and understand the code

In addition, we have written an emacs configuration file to help you format the code correctly

8.1. Row length

The number of characters in each line of code shall not exceed 80

We also recognize that this rule is controversial, but many existing codes have followed this rule, and we feel that consistency is more important

advantage:

They advocate the principle of forced window resizing Many people do not arrange several code windows at the same time, and there is no extra space to stretch the window at all Everyone limits the maximum size of the window, and 80 column width is the traditional standard Why change?

Disadvantages:

Opponents of this principle argue that wider lines of code are easier to read The limitation of 80 columns is the old-fashioned defect of mainframe in the 1960s; Modern devices have a wider display screen, which can easily display more codes

Conclusion:

80 characters is the maximum Exceptions:

  • If a line of comment contains a command or URL with more than 80 characters, it is allowed to exceed 80 characters for the convenience of copy and paste
  • The #include statement with long path can exceed 80 columns But it should be avoided as much as possible
  • Header file protection can ignore this principle

8.2. Non ASCII characters

Try not to use non ASCII characters and use UTF-8 encoding

Even in English, the text of the user interface should not be hard coded into the source code, so non ASCII characters should be used less Such characters can be included appropriately under special circumstances For example, when analyzing external data files, you can properly hard code non ASCII strings as separators in the data files; More commonly, unit test code (which does not require localization) may contain non ASCII strings In this case, UTF-8 coding should be used, because many tools can understand and process UTF-8 coding

Hexadecimal coding is also OK, especially when it can enhance readability - for example, "\ xEF\xBB\xBF" is a zero width uninterrupted interval symbol in Unicode, which cannot be seen if it is directly placed in the source file in UTF-8 format without hexadecimal

(Yang.Y note: "\ xEF\xBB\xBF" is usually used as UTF-8 with BOM code mark)

Use u8 prefix to encode the literal value of string with uXXXX escape sequence into UTF-8 Don't use it on string literals with UTF-8 characters, because if the compiler doesn't recognize the source code as UTF-8, the output will go wrong.

Don't use char16 of C++11_ T and char32_t. They have nothing to do with UTF-8 text, wchar_ Similarly, unless you write code to call the Windows API, which is useful to wchar_t extension.

8.3. Space or tab stop

Use only spaces and indent 2 spaces at a time

We use space indentation Do not use character tables in your code You should set the editor to turn the character table into spaces

8.4. Function declaration and definition

The return type and function name are on the same line, and the parameters should be placed on the same line as far as possible. If they can't be placed, the formal parameters should be separated.

The function looks like this:

ReturnType ClassName::FunctionName(Type par_name1, Type par_name2) {
    DoSomething();
    ...
}

If there is too much text in the same line to fit all parameters:

ReturnType ClassName::ReallyLongFunctionName(Type par_name1, Type par_name2,
                                             Type par_name3) {
    DoSomething();
    ...
}

Not even the first parameter:

ReturnType LongClassName::ReallyReallyReallyLongFunctionName(
        Type par_name1,  // 4 space indent
        Type par_name2,
        Type par_name3) {
    DoSomething();  // 2 space indent
    ...
}

Note the following:

  • If the return type and function name cannot be placed in one line, separate lines will be displayed.
  • If the return type is separated from the function declaration or definition, do not indent.
  • The left parenthesis is always on the same line as the function name;
  • There is no space between the function name and the left parenthesis;
  • There is no space between parentheses and parameters;
  • The left brace is always at the end of the same line of the last parameter;
  • If other style rules allow, the right brace is always on the last line of the function alone, or on the same line as the left brace.
  • There is always a space between the right brace and the left brace;
  • All formal parameters in function declaration and definition must be named and consistent;
  • All formal parameters shall be aligned as far as possible;
  • The default indentation is 2 spaces;
  • The parameters after line feed shall be indented with 4 spaces;

If some parameters are not used, annotate the parameter name at the function definition:

// Formal parameters in the interface are always named.
class Shape {
 public:
  virtual void Rotate(double radians) = 0;
}

// Formal parameters in the declaration are always named.
class Circle : public Shape {
 public:
  virtual void Rotate(double radians);
}

// Comment out useless variables in the definition.
void Circle::Rotate(double /*radians*/) {}

Warning

// Poor - if someone wants to implement it in the future, it's hard to guess what the variable is for.
void Circle::Rotate(double) {}

8.5. Lambda expression

Lambda expressions are formatted as other functions format formal parameters and function bodies; The same is true for capture lists.

If captured by reference, leave no space between variable name and &.

int x = 0;
auto add_to_x = [&x](int n) { x += n; };

Short lambda is written as an inline function.

std::set<int> blacklist = {7, 8, 9};
std::vector<int> digits = {3, 9, 1, 8, 4, 7, 1};
digits.erase(std::remove_if(digits.begin(), digits.end(), [&blacklist](int i) {
                return blacklist.find(i) != blacklist.end();
            }),
            digits.end());

8.6. function call

Either write the function call in one line, or line the parameter in parentheses, or start another line and indent four spaces. If there are no other concerns, try to reduce the number of lines as much as possible, such as putting multiple parameters properly in the same line.

The function call follows the following form:

bool retval = DoSomething(argument1, argument2, argument3);

If the same line cannot be placed, it can be broken into multiple lines, and each subsequent line is aligned with the first argument. There is no space after the left parenthesis and before the right parenthesis:

bool retval = DoSomething(averyveryveryverylongargument1,
                          argument2, argument3);

Parameters can also be placed on the next line, indented four spaces:

if (...) {
  ...
  ...
  if (...) {
    DoSomething(
        argument1, argument2,  // 4 space indent
        argument3, argument4);
  }

Putting multiple parameters on the same line is to reduce the number of lines required for function calls, unless it affects readability. Some people think that putting each parameter in an independent line is not only better to read, but also convenient to edit parameters. However, we pay more attention to readability than the so-called parameter editing, and the latter is easier to do:

If some parameters themselves are slightly complex expressions and reduce readability. Then you can directly create a temporary variable to describe the expression and pass it to the function:

int my_heuristic = scores[x] * y + bases[x];
bool retval = DoSomething(my_heuristic, x, y, z);

Or leave it alone and add a note:

bool retval = DoSomething(scores[x] * y + bases[x],  // Score heuristic.
                          x, y, z);

If a parameter is lined up independently and is more helpful for readability, do so.

In addition, if a series of parameters have a certain structure, the parameter format can be determined according to its structure as appropriate:

// Convert widget s through 3x3 matrix
my_widget.Transform(x1, x2, x3,
                    y1, y2, y3,
                    z1, z2, z3);

8.7. List initialization format

You can format 5.20 as you normally format function calls List initialization.

If the list initialization is accompanied by a name, such as a type or variable name, you can format it when the name is a function and {} is the parenthesis of a function call. On the contrary, if it has a name with a length of zero.

// One line list initialization demonstration.
return {foo, bar};
functioncall({foo, bar});
pair<int, int> p{foo, bar};

// When you have to break a line.
SomeFunction(
    {"assume a zero-length name before {"},
    some_other_function_parameter);
SomeType variable{
    some, other, values,
    {"assume a zero-length name before {"},
    SomeOtherType{
        "Very long string requiring the surrounding breaks.",
        some, other values},
    SomeOtherType{"Slightly shorter string",
                  some, other, values}};
SomeType variable{
    "This is too long to fit all in one line"};
MyType m = {  // Note that you can break the line before {.
    superlongvariablename1,
    superlongvariablename2,
    {short, interior, list},
    {interiorwrappinglist,
     interiorwrappinglist2}};

8.8. Conditional statement

Prefer not to use spaces within parentheses The keywords if and else start on a separate line

There are two acceptable formats for basic conditional statements One has a space between parentheses and conditions, and the other does not

The most common is the format without spaces Either is OK, but keep consistency If you are modifying a file, refer to the existing format If you are writing new code, refer to other files in the directory or project If you're still wandering, don't add spaces

if (condition) {  There is no space in parentheses.
  ...  // 2 space indent.
} else {  // else is on the same line as the closing bracket of if.
  ...
}

If you prefer spaces inside parentheses:

if ( condition ) {  // Parentheses next to spaces - not common
  ...  // 2 space indent.
} else {  // else is on the same line as the closing bracket of if.
  ...
}

Notice that in all cases there is a space between the if and the left parenthesis There should also be a space between the right parenthesis and the left brace:

Warning

if(condition)     // Poor - there is no space after IF.
if (condition){   // Bad - {no space in front.
if(condition){    // Make it worse.
if (condition) {  // Can - IF and {are both immediately adjacent to spaces.

Short conditional statements can be written on the same line if readability is enhanced Use only if the statement is simple and the else clause is not used:

if (x == kFoo) return new Foo();
if (x == kBar) return new Bar();

If the statement has else branches, it is not allowed:

Warning

// You can't do this - when there is an ELSE branch, the IF block has only one row
if (x) DoThis();
else DoThat();

Usually, single line statements don't need braces, and it's ok if you like to use them; Complex conditional or circular statements are better readable with braces There are also some items that require if braces to always be used:

if (condition)
  DoSomething();  // 2 space indent.

if (condition) {
  DoSomething();  // 2 space indent.
}

However, if braces are used in one if else branch of the statement, other branches must also use:

Warning

// You can't do this - IF has braces but ELSE doesn't.
if (condition) {
    foo;
} else
    bar;

// You can't do this - ELSE has braces but IF doesn't.
if (condition)
    foo;
else {
    bar;
}
// As long as braces are used for one branch, braces should be used for both branches.
if (condition) {
  foo;
} else {
  bar;
}

8.9. Loop and switch selection statements

switch statements can be segmented with braces to indicate that cases are not connected. In monolingual sentence loops, parentheses can be used but not used. Empty loop body should use {} or continue

The case block in the switch statement can use curly braces or not, depending on your personal preference If used, follow the method described below

If there are enumerated values that do not meet the case condition, the switch should always contain a default match (if there is an input value without case to process, the compiler will alarm) If default should never be executed, simply add an assert:

switch (var) {
  case 0: {  // 2 space indent
    ...      // 4 space indent
    break;
  }
  case 1: {
    ...
    break;
  }
  default: {
    assert(false);
  }
}

In monolingual sentence loops, parentheses can be used or not:

for (int i = 0; i < kSomeNumber; ++i)
    printf("I love you\n");

for (int i = 0; i < kSomeNumber; ++i) {
    printf("I take it back\n");
}

Empty loop body should use {} or continue instead of a simple semicolon

while (condition) {
  // Repeat the cycle until the condition fails.
}
for (int i = 0; i < kSomeNumber; ++i) {}  // - empty circulator.
while (condition) continue;  // Can - contunue indicates that there is no logic.

Warning

while (condition);  // Poor - it seems to be just one part of while/loop.

8.10. Pointer and reference expressions

There should be no space before or after the period or arrow Pointer / address operators (*, &) cannot be followed by spaces

The following is an example of the correct use of pointers and reference expressions:

x = *p;
p = &x;
x = r.y;
x = r->y;
  • Note: ah
  • When accessing members, there is no space before or after a period or arrow
  • There is no space after the pointer operator * or &

When declaring pointer variables or parameters, the asterisk can be next to the type or variable name:

// Good job, space front.
char *c;
const string &str;

// Good, after the space.
char* c;    // But don't forget "char* c, *d, *e,...;"!
const string& str;

Warning

char * c;  // Bad - * spaces on both sides
const string & str;  // Bad - & there are spaces on both sides.

Keep the same style in a single file, so if you modify an existing file, follow the style of the file

8.11. Boolean expression

If a Boolean expression exceeds the standard line width, the line breaking method should be unified

In the following example, the logical and (& &) operator is always at the end of the line:

if (this_one_thing > this_other_thing &&
    a_third_thing == a_fourth_thing &&
    yet_another & last_one) {
  ...
}

Note that the logic and (& &) operators in the above example are at the end of the line This format is very common in Google. You can put all operators at the beginning. You can consider inserting additional parentheses. If used reasonably, it is very helpful to enhance readability In addition, directly use symbolic operators, such as & & and ~, instead of the word and and and compl

8.12. Function return value

It is not necessary to use parentheses in return expressions.

If you used parentheses when writing x = epr, return expr; It can also be done the same way.

Do not use parentheses when the function returns:

return result;                  // The return value is simple without parentheses.
// You can circle complex expressions with parentheses to improve readability.
return (some_long_condition &&
        another_condition);

Warning

return (value);                // After all, you never write var = (value);
return(result);                // return is not a function!

8.13. Variable and array initialization

Use =, () and {}

You can use =, () and {}. The following are true:

int x = 3;
int x(3);
int x{3};
string name("Some Name");
string name = "Some Name";
string name{"Some Name"};

Be careful when initializing the list {...} with STD:: initializer_ The type initialized by the list constructor. When initializing a non empty list, STD:: initializer will be called first_ List, except for empty list initialization, which will call the default constructor in principle. To forcibly disable std::initializer_list constructor, use parentheses instead.

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

In addition, list initialization does not allow rounding of integer types, which can be used to avoid programming errors on some types.

int pi(3.14);  // Can -- pi == 3
int pi{3.14};  // Compile error: narrowing conversion.

8.14. preprocessor directives

Preprocessing instructions do not indent, start at the beginning of the line

Even if the preprocessing instruction is in an indented code block, the instruction should start at the beginning of the line

// - directives at beginning of line
  if (lopsided_score) {
#if DISASTER_PENDING / / correct -- from the beginning of the line.
    DropEverything();
#endif
    BackToNormal();
  }

Warning

// Poor - indented directives
  if (lopsided_score) {
    #if DISASTER_PENDING  // Wrong! "#if" should be placed at the beginning of the line
    DropEverything();
    #endif                // Wrong! "#endif" do not indent
    BackToNormal();
  }

8.15. Class format

The declaration order of access control block is public:, protected:, private:, indenting 1 space at a time

The basic format of class declaration (if you don't know about class annotation, refer to class annotation) is as follows:

class MyClass : public OtherClass {
 public:      // Note that there is 1 space indentation!
  MyClass();  // As usual, 2 spaces are indented.
  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);
};

matters needing attention:

  • All base class names should be placed on the same line as subclass names under the limit of 80 columns
  • Keywords public:, protected:, private: indent 1 space
  • Except for the first keyword (generally public), there should be a blank line before other keywords If the class is small, it can not be empty
  • Do not leave blank lines after these keywords
  • public comes first, then protected, and finally private

8.16. Constructor initializer list

The list of constructor initializers is placed on the same line or four indented lines side by side

The following two initial value list methods are acceptable:

// When all in one line is appropriate:
MyClass::MyClass(int var) : some_var_(var), some_other_var_(var + 1) {

or

// If you want to break into multiple lines, indent four spaces and put a colon on the first line to initialize the sentence:
MyClass::MyClass(int var)
    : some_var_(var),             // 4 space indent
      some_other_var_(var + 1) {  // aim
  ...
  DoSomething();
  ...
}

8.17. Format space name

Namespace content is not indented

Do not add additional indentation levels to the namespace, for example:

namespace {

void foo() {  // correct. There is no extra indentation in the namespace.
  ...
}

}  // namespace

Do not indent namespaces:

Warning

namespace {

  // No, the indentation is redundant.
  void foo() {
    ...
  }

}  // namespace

When declaring nested namespaces, each namespace is on a separate line.

namespace foo {
namespace bar {

8.18. Horizontal Whitespace

The use of horizontal white space should be adjusted to local conditions Never add meaningless white space at the end of a line

General:

void f(bool b) {  // There is always a space before the left brace.
  ...
int i = 0;  // No space before semicolon.
int x[] = { 0 };  // The inside of braces can be close to or not close to the space, but it should be added on both sides.
int x[] = {0};
// There is always a space before and after the colon in the inheritance and initialization list.
class Foo : public Bar {
 public:
  // As for the implementation of inline functions, add spaces inside braces and write the implementation.
  Foo(int b) : Bar(), baz_(b) {}  // If the braces are empty, no spaces are added.
  void Reset() { baz_ = 0; }  // Use parentheses to separate braces from implementations.
  ...

Adding redundant white space will put an additional burden on others when editing Therefore, leave no spaces at the end of the line If it is determined that a line of code has been modified, remove the redundant spaces; Or remove it when cleaning up the space (make sure no one else is dealing with it) (Yang.Y note: most code editors now support automatic deletion of line beginning / end spaces after a little setting. If not, consider changing an editor or IDE)

Loop and conditional statements:

if (b) {          // if conditional statements and circular statements have spaces after keywords.
} else {          // There are spaces before and after else.
}
while (test) {}   // Parentheses are not immediately adjacent to spaces.
switch (i) {
for (int i = 0; i < 5; ++i) {
switch ( i ) {    // The parentheses of loop and conditional statements can be immediately adjacent to spaces.
if ( test ) {     // Parentheses, but this is rare. In short, be consistent.
for ( int i = 0; i < 5; ++i ) {
for ( ; i < 5 ; ++i) {  // In circulation; There is always a space after,; You can add a space before.
switch (i) {
  case 1:         // There is no space before the colon of switch case.
    ...
  case 2: break;  // If the colon has code, add a space.

Operator:

// There is always a space before and after the assignment operating system.
x = 0;

// Other binary operators always have spaces before and after, but it is OK to leave no spaces before and after factors.
// Parentheses are not immediately adjacent to spaces.
v = w * x + y / z;
v = w*x + y/z;
v = w * (x + z);

// No spaces between arguments and unary operators.
x = -5;
++x;
if (x && !y)
  ...

Templates and transformations:

// Scream brackets (< and >) are not immediately adjacent to spaces, < are not preceded by spaces, and > (are not between).
vector<string> x;
y = static_cast<char*>(x);

// You can also leave a space between the type and the pointer operator, but keep it consistent.
vector<char *> x;
set<list<string>> x;        // This can be used in C++11 code.
set<list<string> > x;       // In C++03, leave a space in > >.

// You may be able to add a pair of symmetrical spaces to < <.
set< list<string> > x;

8.19. Vertical Whitespace

The less vertical space the better

It's not just a matter of rules, it's a matter of principle: don't use blank lines as a last resort In particular: no more than 2 blank lines should be left between two function definitions, no blank lines should be left at the beginning and end of the function body, and no blank lines should be added to the function body at will

The basic principle is: the more code can be displayed on the same screen, the easier it is to understand the control flow of the program Of course, too dense code blocks are as ugly as too loose code blocks, depending on your judgment But usually the less vertical white space the better

The experience of empty line is as follows:

  • Empty lines at the beginning or end of a function body are barely readable.
  • Adding blank lines to multiple if else blocks may be a bit readable.

Notes of the translator (Yule Fox)

  1. For the code format, it varies from person to person and system, and each has its own advantages and disadvantages, but it is necessary to follow the same standard in the same project;
  2. In principle, the row width shall not exceed 80 columns, and it is unreasonable to occupy all the 22 inch display screens;
  3. Try not to use non ASCII characters. If so, refer to UTF-8 format (especially under UNIX/Linux, wide characters can be considered under Windows), and try not to couple string constants into code, such as independent resource files, which is not just a matter of style;
  4. Use spaces unconditionally under UNIX/Linux, and it is understandable to use Tab if MSVC;
  5. Function parameters, logical conditions, initialization list: either all parameters and function names are placed on the same line, or all parameters are side by side;
  6. Except that the left brace of the function definition can be placed at the beginning of the line, including the function / class / structure / enumeration declaration, the left brace of various statements can be placed at the end of the line, and all the right braces form an independent line;
  7. . / - > there is no space before and after the operator, * / & don't leave both before and after, just one, left and right, according to everyone's preference;
  8. Preprocessing instructions / namespaces do not use additional indentation, and classes / structures / enumerations / functions / statements use indentation;
  9. Initialization = or () according to personal preference, just unify;
  10. return don't add ();
  11. Don't abuse the horizontal / vertical white space. It's easy to read and easy to read
  12. On the UNIX/Linux style, why should the left brace be placed at the end of the line (the function implementation of the cc file, and the left brace is at the beginning of the line), my understanding is that the code looks relatively simple. Think about the beginning of the line, except that the function body is enclosed by a pair of braces, the code with only the right brace does look comfortable; The advantage of Windows style is that the matching is clear at a glance

acgtyrant notes

  1. The 80 line limit actually helps to avoid runaway code readability, such as super multiple nested blocks, super multiple function calls, and so on.
  2. After setting Locale on Linux, you can set the coding of all development environments almost once and for all, unlike the wonderful Windows
  3. Google emphasizes that when there is a pair of if else, whether nested or not, there should be curly braces. Apple just stumbled
  4. In fact, I advocate that the pointer / address operator is next to the variable name, int* a, b vs int *a, b. novices will mistakenly think that b of the former is an int * variable, but the latter is different. It is superior and inferior.
  5. In this style guide, I just learned that C + + used to have so-called Alternative operator representations, which may not be used by anyone.
  6. Note that constructor Initializer List and Initializer List are two different things, and I almost confused their translation.
  7. In fact, if you are familiar with the writing rules of English itself, you will find that the format of the style guide is quite consistent with English grammar. For example, if there is text after ordinary punctuation and words, there will always be a space; There is no need to leave between special symbols and words, such as parentheses and true in if (true)
  8. This style guide does not specify whether to use the return statement in the void function, but it is not written in the Google open source project leveldb; Is a blank return statement at the end of a function who return type is void necessary? Look, return; Return; More conventional (in fact, cpprint will report an error to the latter, indicating that there are redundant spaces before the semicolon), and can be used to jump out of the function stack in advance.

Added by j_miguel_y on Thu, 03 Mar 2022 05:40:10 +0200