• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# C++ Coding Style Guide
2
3## <a name="c0-1"></a> Purpose
4Rules are not perfect. Disabling useful features in specific situations may affect code implementation. However, the rules are formulated "to help most programmers to get more benefits". If a rule is found unhelpful or difficult to follow in team coding, please send your feedback to us so we can improve the rule accordingly.
5Before referring to this guide, you are expected to have the following basic capabilities for C++. It is not for a beginner that wants to learn about C++.
61. Have a general knowledge of ISO standards for C++.
72. Be familiar with the basic features of C++, including those of C++ 03/11/14/17.
83. Have a general knowledge of the C++ Standard Library.
9
10## <a name="c0-2"></a>General Principles
11Code must meet the requirements for readability, maintainability, security, reliability, testability, efficiency, and portability while ensuring functionality correctness.
12
13## <a name="c0-3"></a> Key Points
141. C++ programming style, such as naming and typesetting.
152. C++ modular design, including how to design header files, classes, interfaces, and functions.
163. Best practices of C++ features, including constants, type casting, resource management, and templates.
174. Best practices of modern C++, including conventions that can improve code maintainability and reliability in C++ 11/14/17.
18
19
20## <a name="c0-4"></a> Conventions
21**Rule**: a regulating principle that must be followed during programming.
22
23**Recommendation**: a guideline that must be considered during programming.
24
25This document is applicable to standard C++ versions (C++ 03/11/14/17) unless otherwise specified in the rule.
26
27## <a name="c0-5"></a> Exceptions
28It is necessary to understand the reason for each rule or recommendation and to try and comply with them.
29However, some rules and recommendations have exceptions.
30
31The only acceptable exceptions are those that do not violate the general principles and provide appropriate reasons for the exception.
32Try to avoid exceptions because they affect the code consistency. Exceptions to 'Rules' should be very rare.
33
34The style consistency principle is preferred in the following case:
35When you modify external open source or third-party code, the existing code specifications prevail.
36
37# <a name="c2"></a>2 Naming
38## <a name="c2-1"></a>General Naming Rules
39__CamelCase__
40CamelCase is the practice of writing compound words or phrases so that each word or abbreviation in the phrase begins with a capital letter, with no intervening spaces or punctuation.
41There are two conventions:  UpperCamelCase and lowerCamelCase.
42
43
44| Type                                     | Naming Style                             |
45| ---------------------------------------- | ---------------------------------------- |
46| Class Type, Struct Type, Enumeration Type, and Union Type Definitions, Scope Name | UpperCamelCase                           |
47| Functions (Including Global Functions, Scope Functions, and Member Functions) | UpperCamelCase                           |
48| Global Variables (Including Variables of the Global and Namespace Scopes, Namespace Variables, and Class Static Variables), Local Variables, Function Parameters, and Class, Struct, and Union Member Variables | lowerCamelCase                           |
49| Macro, Constant, Enumerated Value, goto Tag | All caps, separated with underscores (`_`) |
50
51Note:
52**Constant** indicates the variables of the basic, enumeration, or character string type modified by const or constexpr in the global scope, the namespace scope, and the scope of a static member of a class.
53**Variable** indicates the variables excluding those defined in **Constant**. These variables use the lowerCamelCase style.
54
55## <a name="c2-2"></a> File Names
56### <a name="a2-2-1"></a> Recommendation 2.2.1 Use .cpp as the C++ file name extension and .h as the header file name extension.
57It is recommended that you use .h as the name extension of a header file so that the header file can be directly compatible with C and C++.
58It is recommended that you use .cpp as the name extension of an implementation file. In this way, you can directly distinguish C++ code from C code.
59
60At present, there are some other file name extensions used by programmers:
61
62- Header files:  .hh, .hpp, .hxx
63- Implementation files: .cc, .cxx, .C
64
65If your project team uses a specific file name extension, you can continue to use it and keep the style consistent.
66This document uses .h and .cpp extensions.
67
68
69### <a name="a2-2-2"></a>Recommendation 2.2.2 Keep C++ file names the same as the class name.
70The names of the C++ header file and the C++ implementation file must be the same as the class name. Use the CamelCase or Kernel style and keep the style consistent.
71
72For example, if there is a class named DatabaseConnection, the corresponding file names are as follows:
73- database_connection.h
74- database_connection.cpp
75
76The naming rules of struct, namespace, and enumeration definition files are similar to the rules above.
77
78## <a name="c2-3"></a> Function Names
79Functions are named in UpperCamelCase. Generally, the verb or verb-object structure is used.
80```cpp
81class List {
82public:
83	void AddElement(const Element& element);
84	Element GetElement(const unsigned int index) const;
85	bool IsEmpty() const;
86};
87
88namespace Utils {
89    void DeleteUser();
90}
91```
92
93## <a name="c2-4"></a> Type Names
94
95Types are named in the UpperCamelCase style.
96All types, such as classes, structs, unions, typedefs, and enumerations, use the same conventions. For example:
97```cpp
98// classes, structs and unions
99class UrlTable { ...
100class UrlTableTester { ...
101struct UrlTableProperties { ...
102union Packet { ...
103
104// typedefs
105typedef std::map<std::string, UrlTableProperties*> PropertiesMap;
106
107// enums
108enum UrlTableErrors { ...
109```
110
111For namespace naming, UpperCamelCase is recommended.
112```cpp
113// namespace
114namespace OsUtils {
115
116namespace FileUtils {
117
118}
119
120}
121```
122
123
124### <a name="a2-4-1"></a>Recommendation 2.4.1 Do not abuse typedef or #define to alias basic types.
125Unless otherwise specified, do not use typedef or #define to redefine a basic value type.
126The basic types found in the `<cstdint>` header file are preferable.
127
128| Signed Type | Unsigned Type | Description                              |
129| ----------- | ------------- | ---------------------------------------- |
130| int8_t      | uint8_t       | The signed or unsigned 8-bit integer type. |
131| int16_t     | uint16_t      | The signed or unsigned 16-bit integer type. |
132| int32_t     | uint32_t      | The signed or unsigned 32-bit integer type. |
133| int64_t     | uint64_t      | The signed or unsigned 64-bit integer type. |
134| intptr_t    | uintptr_t     | The signed or unsigned integer type large enough to hold a pointer. |
135
136
137## <a name="c2-5"></a> Variable Names
138General variables are named in lowerCamelCase, including global variables, function parameters, local variables, and member variables.
139```cpp
140std::string tableName;  // Good: Recommended style.
141std::string tablename;  // Bad: Forbidden style.
142std::string path;       // Good: When there is only one word, lowerCamelCase (all lowercase) is used.
143```
144
145### <a name="r2-5-1"></a>Rule 2.5.1 Add the prefix 'g_' to global variables. Do not add a prefix to a static variable.
146Global variables should be used as little as possible, and special attention should be paid to the use of global variables. This prefix highlights global variables so that developers can be more careful when handling them.
147- Global static variables and global variables are named in the same way.
148- Static variables and common local variables in functions are named in the same way.
149- Static member variables and common member variables of classes are named in the same way.
150
151```cpp
152int g_activeConnectCount;
153
154void Func()
155{
156    static int packetCount = 0;
157    ...
158}
159```
160
161### <a name="r2-5-2"></a>Rule 2.5.2 Name member variables in classes based on the three styles of the lowerCamelCase and maintain a uniform coding style for a product or project.
162
163```cpp
164class Foo {
165private:
166    std::string fileName_;   // Add the _ postfix, similar to the K&R naming style.
167};
168```
169Use the lowerCamelCase style and do not add prefixes or suffixes to name a member variable of the struct or union type. Keep the naming style consistent with that for a local variable.
170
171## <a name="c2-6"></a> Macro, Constant, and Enumeration Names
172For macros and enumerated values, use all caps separated with underscores (`_`).
173In the global scope, constants of named and unnamed namespaces and static member constants should be capitalized and separated with underscores (`_`). Local constants and ordinary const member variables use the lowerCamelCase naming style.
174
175```cpp
176#define MAX(a, b) (((a) < (b))? (b): (a)) // Though examples of Macro names are made, you are not advised to use macros to implement this function.
177
178enum BaseColor {    // Note: Enumerated types are named in the UpperCamelCase style, while their values are all capitalized and separated with underscores (_).
179    RED,
180    DARK_RED,
181    GREEN,
182    LIGHT_GREEN
183};
184
185int Func(...)
186{
187    const unsigned int bufferSize = 100;    // Local variable
188    char *p = new char[bufferSize];
189    ...
190}
191
192namespace Utils {
193	const unsigned int DEFAULT_FILE_SIZE_KB = 200;        // Global variable
194}
195
196```
197
198# <a name="c3"></a>3 Formatting
199
200## <a name="c3-1"></a>Line Length
201
202### <a name="a3-1-1"></a>Recommendation 3.1.1 Each line of code should contain a maximum of 120 characters.
203** Note: **It is recommended that the number of characters in each line not exceed 120. It is recommended that the number of characters in each line not exceed 120. If the line of code exceeds the permitted length, wrap the line appropriately.
204
205Exception:
206- If a one-line comment contains a command or URL of more than 120 characters, you can keep the line for ease in using copy, paste, and search using the grep command.
207- The length of an `#include` statement can contain a long path exceeding 120 characters, but this should be avoided if possible.
208- The error information in preprocessor directives can exceed the permitted length.
209  Put the error information of preprocessor directives in one line to facilitate reading and understanding even if the line contains more than 120 characters.
210```cpp
211#ifndef XXX_YYY_ZZZ
212#error Header aaaa/bbbb/cccc/abc.h must only be included after xxxx/yyyy/zzzz/xyz.h, because xxxxxxxxxxxxxxxxxxxxxxxxxxxxx
213#endif
214```
215
216## <a name="c3-2"></a>Indentation
217
218### <a name="r3-2-1"></a>Rule 3.2.1 Use spaces to indent and indent 4 spaces at a time.
219Only spaces can be used for indentation. Four spaces are indented each time. Do not use the Tab character to indent.
220Currently, almost all IDEs support automatic expansion of a Tab to 4 spaces upon pressing the tab key. Please configure your IDE to do so.
221
222## <a name="c3-3"></a>Braces
223### <a name="r3-3-1"></a>Rule 3.3.1 Use the K&R indentation writing style.
224__K&R style__
225When a line break is required, the left brace of a function (excluding the lambda statement) starts a new line. One space should be placed between the statement and the brace.
226The right brace starts a new line and nothing else is placed on the line, unless it is followed by the remaining part of the same statement, for example,  "while" in the do statement, "else" or "else if" in the if statement, a comma,  and a semicolon.
227
228For example:
229```cpp
230struct MyType {     // Follow the statement to the end, and indent one space.
231    ...
232};
233
234int Foo(int a)
235{                   // The left brace of the function starts a new line, nothing else is placed on the line.
236    if (...) {
237        ...
238    } else {
239        ...
240    }
241}
242```
243The reasons for recommending this style are as follows:
244
245- Code is more compact.
246- Placing the brace at the end of the statement makes the code more continuous in reading rhythm than starting a new line.
247- This style complies with mainstream norms and habits of programming languages.
248- Most modern IDEs have an automatic code indentation, alignment and display. Placing the brace at the end of a line does not impact understanding.
249
250
251If no function body is inside the braces, the braces can be put on the same line.
252```cpp
253class MyClass {
254public:
255    MyClass() : value_(0) {}
256
257private:
258    int value_;
259};
260```
261
262## <a name="c3-4"></a>  Function Declarations and Definitions
263
264### <a name="r3-4-1"></a>Rule 3.4.1 The return type and the function name of a function declaration or definition must be on the same line. When the length of the function parameter list exceeds the permitted length, a line break is required and parameters must be aligned appropriately.
265When a function is declared or defined, the return value type of the function should be on the same line as the function name. If the line length permits, the function parameters should be placed on the same line. Otherwise, the function parameters should be wrapped and properly aligned.
266The left parenthesis of a parameter list should always be on the same line as the function name. The right parenthesis always follows the last parameter.
267
268The following is an example of line breaks:
269```cpp
270ReturnType FunctionName(ArgType paramName1, ArgType paramName2)   // Good: All are in the same line.
271{
272    ...
273}
274
275ReturnType VeryVeryVeryLongFunctionName(ArgType paramName1,     // Each added parameter starts on a new line because the line length limit is exceeded.
276                                        ArgType paramName2,     // Good: aligned with the previous parameter.
277                                        ArgType paramName3)
278{
279    ...
280}
281
282ReturnType LongFunctionName(ArgType paramName1, ArgType paramName2, // Parameters are wrapped because the line length limit is exceeded.
283    ArgType paramName3, ArgType paramName4, ArgType paramName5)     // Good: After the line break, 4 spaces are used for indentation.
284{
285    ...
286}
287
288ReturnType ReallyReallyReallyReallyLongFunctionName(            // The line length cannot accommodate even the first parameter, and a line break is required.
289    ArgType paramName1, ArgType paramName2, ArgType paramName3) // Good: After the line break, 4 spaces are used for indentation.
290{
291    ...
292}
293```
294
295## <a name="c3-5"></a>Function Calls
296### <a name="r3-5-1"></a>Rule 3.5.1 A function call parameter list should be placed on one line. When the parameter list exceeds the line length and requires a line break, the parameters should be properly aligned.
297A function call parameter list should be placed on one line. When the parameter list exceeds the line length and requires a line break, the parameters should be properly aligned.
298The left parenthesis always follows the function name, and the right parenthesis always follows the last parameter.
299
300The following are examples of proper line breaks:
301```cpp
302ReturnType result = FunctionName(paramName1, paramName2);   // Good: All function parameters are on one line.
303
304ReturnType result = FunctionName(paramName1,
305                                 paramName2,                // Good: aligned with the previous parameter
306                                 paramName3);
307
308ReturnType result = FunctionName(paramName1, paramName2,
309    paramName3, paramName4, paramName5);                    // Good: Parameters are wrapped. After the line break, 4 spaces are used for indentation.
310
311ReturnType result = VeryVeryVeryLongFunctionName(           // The line length cannot accommodate even the first parameter, and a line break is required.
312    paramName1, paramName2, paramName3);                    // After the line break, 4 spaces are used for indentation.
313```
314
315If some of the parameters called by a function are associated with each other, you can group them for better understanding.
316```cpp
317// Good: The parameters in each line represent a group of data structures with strong correlation. They are placed on a line for ease of understanding.
318int result = DealWithStructureLikeParams(left.x, left.y,     // A group of related parameters.
319                                         right.x, right.y);  // Another group of related parameters.
320```
321
322## <a name="c3-6"></a> if Statements
323
324### <a name="r3-6-1"></a>Rule 3.6.1 Use braces to include an if statement.
325We require that all if statements use braces, even if there is only one statement.
326
327Reasons:
328- The logic is intuitive and easy to read.
329- It is less prone to mistakes when new code is added to the existing if statement.
330- If function-like macros are used in a conditional statement, it is less prone to mistakes (in case the braces are missing when macros are defined).
331
332```cpp
333if (objectIsNotExist) {         // Good: Braces are added to a single-line conditional statement.
334    return CreateNewObject();
335}
336```
337### <a name="r3-6-2"></a>Rule 3.6.2 Place if, else, and else if keywords on separate lines.
338If there are multiple branches in a conditional statement, they should be placed on separate lines.
339
340Good example:
341
342```cpp
343if (someConditions) {
344    DoSomething();
345    ...
346} else {  // Good: Put the if and else keywords on separate lines.
347    ...
348}
349```
350
351Bad example:
352
353```cpp
354if (someConditions) { ... } else { ... } // Bad: The if and else keywords are put on the same line.
355```
356
357## <a name="c3-7"></a> Loop Statements
358### <a name="r3-7-1"></a>Rule 3.7.1 Use braces after loop statements.
359Similar to if statements, we require that the for and while loop statements contain braces, even if the loop body is empty or there is only one loop statement.
360```cpp
361for (int i = 0; i < someRange; i++) {   // Good: Braces are used.
362    DoSomething();
363}
364```
365```cpp
366while (condition) {} // Good: The while loop body is empty. Braces should be used.
367```
368```cpp
369while (condition) {
370    continue; // Good: The continue keyword highlights the end of the empty loop. Braces should be used.
371}
372```
373
374Bad example:
375```cpp
376for (int i = 0; i < someRange; i++)
377    DoSomething();      // Bad: Braces are mandatory.
378```
379```cpp
380while (someCondition) ; // Bad: Using a semicolon here will make people misunderstand that it is a part of the while statement and not the end to it.
381```
382
383## <a name="c3-8"></a> Switch Statements
384### <a name="r3-8-1"></a>Rule 3.8.1 Indent case and default in a switch statement with four spaces.
385The indentation style of the switch statement is as follows:
386```cpp
387switch (var) {
388    case 0:             // Good: Indented
389        DoSomething1(); // Good: Indented
390        break;
391    case 1: {           // Good: Braces are added.
392        DoSomething2();
393        break;
394    }
395    default:
396        break;
397}
398```
399
400```cpp
401switch (var) {
402case 0:                 // Bad: case is not indented.
403    DoSomething();
404    break;
405default:                // Bad: default is not indented.
406    break;
407}
408```
409
410## <a name="c3-9"></a> Expressions
411
412### <a name="a3-9-1"></a>Recommendation 3.9.1 Keep a consistent line break style for expressions and ensure that operators are placed at the end of a line.
413A long expression that does not meet the line length requirement must be wrapped appropriately. Generally, the expression is wrapped at an operator of a lower priority or a connector, and the operator or connector is placed at the end of the line.
414Placing these at the end of a line indicates that the operation is to be continued on the next line.
415For example:
416
417// Assume that the first line exceeds the length limit.
418```cpp
419if (currentValue > threshold &&  // Good: After the line break, the logical-AND operators are placed at the end of the line.
420    someConditionsion) {
421    DoSomething();
422    ...
423}
424
425int result = reallyReallyLongVariableName1 +    // Good
426             reallyReallyLongVariableName2;
427```
428After an expression is wrapped, ensure that the lines are aligned appropriately or indented with 4 spaces. See the following example.
429
430```cpp
431int sum = longVaribleName1 + longVaribleName2 + longVaribleName3 +
432    longVaribleName4 + longVaribleName5 + longVaribleName6;         // Good: indented with 4 spaces
433
434int sum = longVaribleName1 + longVaribleName2 + longVaribleName3 +
435          longVaribleName4 + longVaribleName5 + longVaribleName6;   // Good: The lines are aligned.
436```
437## <a name="c3-10"></a> Variable Assignment
438
439### <a name="r3-10-1"></a>Rule 3.10.1 Multiple variable definitions and assignment statements cannot be written on one line.
440Each line should have only one variable initialization statement. It is easier to read and understand.
441
442```cpp
443int maxCount = 10;
444bool isCompleted = false;
445```
446
447Bad example:
448
449```cpp
450int maxCount = 10; bool isCompleted = false; // Bad: Multiple variable initialization statements must be separated on different lines. Each variable initialization statement occupies one line.
451int x, y = 0;  // Bad: Multiple variable definitions must be separated on different lines. Each definition occupies one line.
452
453int pointX;
454int pointY;
455...
456pointX = 1; pointY = 2;  // Bad: Multiple variable assignment statements must be separated on different lines.
457```
458Exception: Multiple variables can be declared and initialized in the for loop header, if initialization statement (C++17), and structured binding statement (C++17). Multiple variable declarations in these statements have strong associations. Forcible division into multiple lines may cause problems such as scope inconsistency and separation of declaration from initialization.
459
460## <a name="c3-11"></a> Initialization
461Initialization is applicable to structs, unions, and arrays.
462
463### <a name="r3-11-1"></a>Rule 3.11.1 When an initialization list is wrapped, ensure that the line after the break is indented and aligned properly.
464If a structure or array initialization list is wrapped, the line after the break is indented with four spaces.
465Choose the wrap location and alignment style for best comprehension.
466
467```cpp
468const int rank[] = {
469    16, 16, 16, 16, 32, 32, 32, 32,
470    64, 64, 64, 64, 32, 32, 32, 32
471};
472```
473
474## <a name="c3-12"></a> Pointers and References
475### <a name="a3-12-1"></a>Recommendation 3.12.1 The pointer type `*` follows a variable name or type. There can be only one space to the side of it.
476Pointer naming: There can be only one space next to `*`.
477```cpp
478int* p = NULL;  // Good
479int *p = NULL;  // Good
480
481int*p = NULL;   // Bad
482int * p = NULL; // Bad
483```
484
485Exception: When a variable is modified by const or restrict, `*` cannot follow the variable or type.
486```cpp
487const char * const VERSION = "V100";
488```
489
490### <a name="a3-12-2"></a>Recommendation 3.12.2 The reference type `&` follows a variable name or type. There can be only one space to the side of it.
491Reference naming: There can be only one space around `&`.
492```cpp
493int i = 8;
494
495int& p = i;     // Good
496int &p = i;     // Good
497int*& rp = pi; // Good: The reference type `*&` follows the type.
498int *&rp = pi; // Good: The reference type `*&` follows the variable name.
499int* &rp = pi; // Good: The pointer type `*` follows the type and the eference type `&` follows the variable name.
500
501int & p = i;    // Bad
502int&p = i;      // Bad
503```
504
505## <a name="c3-13"></a> Preprocessor Directives
506### <a name="r3-13-1"></a>Rule 3.13.1 The number sign (#) that starts a preprocessor directive must be at the beginning of the line and can be indented in nested preprocessor directives.
507The number sign (#) that starts a preprocessor directive must be at the beginning of the line even through the preprocessor directive is inside a function.
508
509```cpp
510#if defined(__x86_64__) && defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_16) // Good: "#" is at the beginning of the line.
511#define ATOMIC_X86_HAS_CMPXCHG16B 1  // Good: "#" is at the beginning of the line.
512#else
513#define ATOMIC_X86_HAS_CMPXCHG16B 0
514#endif
515
516
517int FunctionName()
518{
519    if (someThingError) {
520        ...
521#ifdef HAS_SYSLOG        // Good: Even in the function body, "#" is at the beginning of the line.
522        WriteToSysLog();
523#else
524        WriteToFileLog();
525#endif
526    }
527}
528```
529The nested preprocessor directives starting with `#` can be indented and aligned based on a standardized style.
530
531```cpp
532#if defined(__x86_64__) && defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_16)
533    #define ATOMIC_X86_HAS_CMPXCHG16B 1 // Good: wrapped for easier comprehension
534#else
535    #define ATOMIC_X86_HAS_CMPXCHG16B 0
536#endif
537```
538
539## <a name="c3-14"></a> Whitespace
540### <a name="r3-14-1"></a>Rule 3.14.1 Ensure that horizontal spaces are used to highlight keywords and important information, and avoid unnecessary whitespace.
541Horizontal spaces are used to highlight keywords and important information. Spaces are not allowed at the end of each code line. The general rules are as follows:
542
543- Add spaces after keywords such as if, switch, case, do, while, and for.
544- Do not add spaces after the left parenthesis or before the right parenthesis.
545- For expressions enclosed by braces, either add a space on either side or avoid a space on either side.
546- Do not add spaces after any unary operator (& * + - ~ !).
547- Add a space to the left and right sides of each binary operator (= + -< > * /% | & ^ <= >= == !=).
548- Add spaces to the left and right sides of a ternary operator (? :).
549- Do not add spaces between a prefix or suffix increment (++) or decrement (--) operator and a variable.
550- Do not add spaces before or after a struct member operator (. ->).
551- Do not add spaces before commas. Add spaces after commas.
552- Do not add spaces between a template or type conversion operator (<>) and a type.
553- Do not add spaces before or after a domain operator (::).
554- Determine whether to add spaces before and after a colon (:) based on the actual situation.
555
556In normal cases:
557```cpp
558void Foo(int b) {  // Good: A space is added before the left brace.
559
560int i = 0;  // Good: During variable initialization, there should be spaces before and after =. Do not leave a space before the semicolon.
561
562int buf[BUF_SIZE] = {0}; // Good: Spaces are not added in braces.
563```
564
565Function definition and call:
566```cpp
567int result = Foo(arg1,arg2);
568                    ^    // Bad: A space should be added after the comma.
569
570int result = Foo( arg1, arg2 );
571                 ^          ^  // Bad: Spaces should not be added after the left parenthesis or before the right parenthesis.
572```
573
574Pointer and Address Operator
575```cpp
576x = *p;     // Good: There is no space between the operator * and the pointer p.
577p = &x;     // Good: There is no space between the operator & and the variable x.
578x = r.y;    // Good: When a member variable is accessed through the operator (.), no space is added.
579x = r->y;   // Good: When a member variable is accessed through the operator (->), no space is added.
580```
581
582Other Operators:
583```cpp
584x = 0;   // Good: There is a space before and after the assignment operator (=).
585x = -5;  // Good: There is no space between the minus sign (–) and the number.
586++x;     //Good: Do not add spaces between a prefix or suffix increment (++) or decrement (--) operator and a variable..
587x--;
588
589if (x && !y) // Good: There is a space before and after the Boolean operator. There is no space between the ! operator and the variable.
590v = w * x + y / z;  // Good: There is a space before and after the binary operator.
591v = w * (x + z);    // Good: There is no space before or after the expression in the parentheses.
592
593int a = (x < y) ? x : y;  // Good: Ternary operator. There is a space before and after ? and :
594```
595
596Loops and Conditional Statements:
597```cpp
598if (condition) {  // Good: There is a space between the if keyword and the left parenthesis, and no space before or after the conditional statement in the parentheses.
599    ...
600} else {           // Good: There is a space between the else keyword and the left brace.
601    ...
602}
603
604while (conditions) {}   // Good: There is a space between the while keyword and the left parenthesis. There is no space before or after the conditional statement in the parentheses.
605
606for (int i = 0; i < someRange; ++i) {  // Good: There is a space between the for keyword and the left parenthesis, and after the semicolon.
607    ...
608}
609
610switch (condition) {  // Good: There is a space after the switch keyword.
611    case 0:     // Good: There is no space between the case condition and the colon.
612        ...
613        break;
614    ...
615    default:
616        ...
617        break;
618}
619```
620
621Templates and Conversions
622```cpp
623// Angle brackets (< and >) are not adjacent to space. There is no space before < or between > and (.
624vector<string> x;
625y = static_cast<char*>(x);
626
627// There can be a space between the type and the pointer operator. Keep the spacing style consistent.
628vector<char *> x;
629```
630
631Scope Operators
632```cpp
633std::cout;    // Good: Namespace access. Do not leave spaces.
634
635int MyClass::GetValue() const {}  // Good: Do not leave spaces in the definition of member functions.
636```
637
638Colons
639```cpp
640// Scenarios when space is required
641
642// Good: // Add a space before or after the colon in a derived class definition.
643class Sub : public Base {
644
645};
646
647// Add a space before or after the colon in the initialization list of a constructor function.
648MyClass::MyClass(int var) : someVar_(var)
649{
650    DoSomething();
651}
652
653// Add a space before or after the colon in a bit-field.
654struct XX {
655    char a : 4;
656    char b : 5;
657    char c : 4;
658};
659```
660
661```cpp
662// Scenarios when space is not required
663
664// Good: // No space is added before or after the colon next to a class access permission (public or private).
665class MyClass {
666public:
667    MyClass(int var);
668private:
669    int someVar_;
670};
671
672// No space is added before or after the colon in a switch statement.
673switch (value)
674{
675    case 1:
676        DoSomething();
677        break;
678    default:
679        break;
680}
681```
682
683Note: Currently, all IDEs support automatic deletion of spaces at the end of a line. Please configure your IDE correctly.
684
685### <a name="a3-14-1"></a>Recommendation 3.14.1 Use blank lines only when necessary to keep code compact.
686
687There must be as few blank lines as possible so that more code can be displayed for easy reading. Recommendations:
688- Add blank lines according to the correlation between lines.
689- Consecutive blank lines are not allowed inside functions, type definitions, macros, and initialization expressions.
690- A maximum of **two** consecutive blank lines can be used.
691- Do not add blank lines on the first and last lines of a code block in braces. This recommendation is not applicable to code block in braces of a namespace.
692
693```cpp
694int Foo()
695{
696    ...
697}
698
699
700
701int bar() {// Bad: More than one blank lines are used between two function definitions.
702{
703    ...
704}
705
706
707if (...) {
708        // Bad: Do not add blank lines on the first and last lines of a code block.
709    ...
710        // Bad: Do not add blank lines on the first and last lines of a code block.
711}
712
713int Foo(...)
714{
715        // Bad: Do not add blank lines before the first statement in a function body.
716    ...
717}
718```
719
720## <a name="c3-15"></a> Classes
721### <a name="r3-15-1"></a>Rule 3.15.1 Class access specifier declarations are in the sequence: public, protected, private. Indent these specifiers to the same level as the class keyword.
722```cpp
723class MyClass : public BaseClass {
724public:      // Not indented.
725    MyClass();  // Indented with 4 spaces.
726    explicit MyClass(int var);
727    ~MyClass() {}
728
729    void SomeFunction();
730    void SomeFunctionThatDoesNothing()
731    {
732    }
733
734    void SetVar(int var) { someVar_ = var; }
735    int GetVar() const { return someVar_; }
736
737private:
738    bool SomeInternalFunction();
739
740    int someVar_;
741    int someOtherVar_;
742};
743```
744
745In each part, it is recommended that similar statements be put together and in the following order: Type (including typedef, using, nested structs and classes), Constant, Factory Function, Constructor, Assignment Operator, Destructor, Other Member Function, and Data Member
746
747
748### <a name="r3-15-2"></a>Rule 3.15.2 The constructor initialization list must be on the same line or wrapped and aligned with four spaces of indentation.
749```cpp
750// If all variables can be placed on the same line
751MyClass::MyClass(int var) : someVar_(var)
752{
753    DoSomething();
754}
755
756// If the variables cannot be placed on the same line
757// Wrapped at the colon and indented with four spaces
758MyClass::MyClass(int var)
759    : someVar_(var), someOtherVar_(var + 1)  // Good: Add a space after the comma.
760{
761    DoSomething();
762}
763
764//  If an initialization list needs to be placed in multiple lines, put each member on a separate line and align between lines.
765MyClass::MyClass(int var)
766    someVar(var),             // Four spaces of indentation.
767      someOtherVar_(var + 1)
768{
769    DoSomething();
770}
771```
772
773# <a name="c4"></a>4 Comments
774Generally, clear architecture and good naming are recommended to improve code readability, and comments are provided only when necessary.
775Comments are used to help readers quickly understand code. Therefore, **comments should be provided for the sake of readers**.
776
777Comments must be concise, clear, and unambiguous, ensuring that information is complete and not redundant.
778
779**Comments are as important as code**.
780When writing a comment, you need to step into the reader's shoes and use comments to express what the reader really needs. Comments are used to express the function and intention of code, rather than repeating code.
781When modifying the code, ensure that the comments are consistent with the modified code. It is not polite to modify only code and keep the old comments, which will undermine the consistency between code and comments, and may confuse or even mislead readers.
782
783Comments should be made in English.
784
785## <a name="c4-1"></a>Comment Style
786
787In C++ code, both ` /* */` and ` // ` can be used for commenting.
788Comments can be classified into different types, such as file header comments, function header comments, and code comments. This is based on their purposes and positions.
789Comments of the same type must keep a consistent style.
790
791Note: Example code in this document uses comments in the `//` format only to better describe the rules and recommendations. This does not mean this comment format is better.
792
793## <a name="c4-2"></a>  File Header Comments
794### <a name="r4-2-1"></a>Rule 4.2.1 File header comments must contain the copyright notice.
795
796/*
797 * Copyright (c) 2020 Huawei Device Co., Ltd.
798 * Licensed under the Apache License, Version 2.0 (the "License");
799 * you may not use this file except in compliance with the License.
800 * You may obtain a copy of the License at
801    *
802 * http://www.apache.org/licenses/LICENSE-2.0
803    *
804 * Unless required by applicable law or agreed to in writing, software
805 * distributed under the License is distributed on an "AS IS" BASIS,
806 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
807 * See the License for the specific language governing permissions and
808 * limitations under the License.
809    */
810
811## <a name="c4-3"></a> Function Header Comments
812### <a name="r4-3-1"></a> Rule 4.3.1 Function header comments with no content are forbidden.
813Not all functions need function header comments.
814For information that cannot be described by function signatures, add function header comments.
815
816Function header comments are placed above the function declaration or definition. Use one of the following styles:
817Use '//' to start the function header.
818
819```cpp
820// Single-line function header
821int Func1(void);
822
823// Multi-line function header
824// Second line
825int Func2(void);
826```
827
828Use `/*   */` to start the function header.
829```cpp
830/* Single-line function header */
831int Func1(void);
832
833/*
834 * Another single-line function header
835 */
836int Func2(void);
837
838/*
839 * Multi-line function header
840 * Second line
841 */
842int Func3(void);
843```
844Use function names to describe functions, and add function header comments if necessary.
845Do not write useless or redundant function headers. Do not write empty function headers with no content.
846
847The function header comment content will depend on the function and includes but is not limited to: a function description, return value, performance constraints, usage comments, memory conventions, algorithm implementation, reentering requirements.
848In the function interface declaration in the external header file, the function header comment should clearly describe important and useful information.
849
850Good example:
851
852```cpp
853/*
854 * The number of written bytes is returned. If -1 is returned, the write operation failed.
855 * Note that the memory buffer should be released by the caller.
856 */
857int WriteString(const char *buf, int len);
858```
859
860Bad example:
861```cpp
862/*
863 * Function name: WriteString
864 * Function: Write a character string.
865 * Parameters:
866 * Return value:
867 */
868int WriteString(const char *buf, int len);
869```
870Problems:
871
872- The 'Parameters' and 'Return value' have no content.
873- The function name is redundant.
874- The most import thing, that is, who needs to release the buffer, is not clearly stated.
875
876## <a name="c4-4"></a> Code Comments
877### <a name="r4-4-1"></a>Rule 4.4.1 Code comments are placed above or on the right of the corresponding code.
878### <a name="r4-4-2"></a>Rule 4.4.2 There must be a space between the comment character and the comment content. At least one space is required between the comment and code if the comment is placed to the right of code.
879Comments placed above code should be indented the same as that of the code.
880Use one of the following styles:
881Use "//".
882```cpp
883
884// Single-line comment
885DoSomething();
886
887// Multi-line comment
888// Second line
889DoSomething();
890```
891
892Use `/* */`.
893```cpp
894/* Single-line comment */
895DoSomething();
896
897/*
898 * Multi-line comment in another mode
899 * Second line
900 */
901DoSomething();
902```
903Leave at least one space between the code and the comment on the right. It is recommended that no more than four spaces be left.
904You can use the Tab key to indent 1–4 spaces.
905
906Select and use one of the following styles:
907
908```cpp
909int foo = 100;  // Comment on the right
910int bar = 200;  /* Comment on the right */
911```
912It is more appealing sometimes when the comment is placed on the right of code and the comments and code are aligned vertically.
913After the alignment, ensure that the comment is 1–4 spaces away from the widest line of code.
914For example:
915
916```cpp
917const int A_CONST = 100;         /* Related comments of the same type can be aligned vertically. */
918const int ANOTHER_CONST = 200;   /* Leave spaces after code to align comments vertically. */
919```
920When the comment on the right exceeds the line width, consider placing the comment above the code.
921
922### <a name="r4-4-3"></a>Rule 4.4.3 Delete unused code segments. Do not comment them out.
923Code that is commented out cannot be maintained. If you attempt to restore the code, it is very likely to introduce ignorable defects.
924The correct method is to delete unnecessary code directly. If necessary, consider porting or rewriting the code.
925
926Here, commenting out refers to the removal of code from compilation without actually deleting it. This is done by using /* */, //, #if 0, #ifdef NEVER_DEFINED, and so on.
927
928### <a name="a4-4-1"></a>Recommendation 4.4.1 Delivered code cannot contain a TODO/TBD/FIXME comment.
929TODO/TBD comments are used to describe required improvements and supplements.
930FIXME comments are used to describe defects that need fixing.
931They should have a standardized style, which facilitates text search. For example:
932
933```cpp
934// TODO(<author-name>): XX
935// FIXME: XX
936```
937
938
939# <a name="c5"></a>5 Header Files
940## <a name="c5-1"></a> Header File Responsibility
941A header file is an external interface of a module or file. The design of a header file shows most of the system design.
942The interface declaration for most functions is more suitable placed in the header file, but implementation (except inline functions) cannot be placed in the header file. Functions, macros, enumerations, and structure definitions that need to be used in .cpp files cannot be placed in the header file.
943The header responsibility should be simple. An overly complex header file will make dependencies complex and cause long compilation times.
944
945### <a name="a5-1-1"></a>Recommendation 5.1.1 Each .cpp file should have a .h file with the same name. It should be used to declare the classes and interfaces that need to be exposed externally.
946Generally, each .cpp file has a corresponding .h file. This .cpp file is used to store the function declarations, macro definitions, and class definitions that are to be exposed.
947If a .cpp file does not need to open any interface externally, it should not exist.
948Exception: __An entry point (for example, the file where the main function is located), unit tests, and dynamic libraries __
949
950For example:
951```cpp
952// Foo.h
953
954#ifndef FOO_H
955#define FOO_H
956
957class Foo {
958public:
959    Foo();
960    void Fun();
961
962private:
963    int value_;
964};
965
966#endif
967```
968
969```cpp
970// Foo.cpp
971#include "Foo.h"
972
973namespace { // Good: The declaration of the internal function is placed in the header of the .cpp file, and has been limited to the unnamed namespace or static scope.
974    void Bar()
975    {
976    }
977}
978
979...
980
981void Foo::Fun()
982{
983    Bar();
984}
985```
986
987## <a name="c5-2"></a> Header File Dependency
988### <a name="r5-2-1"></a>Rule 5.2.1 Header file cyclic dependency is forbidden.
989An example of cyclic dependency (also known as circular dependency) is: a.h contains b.h, b.h contains c.h, and c.h contains a.h. If any of these header files is modified, all code containing a.h, b.h, and c.h needs to be recompiled.
990For a unidirectional dependency, for example if: a.h contains b.h, b.h contains c.h, and c.h does not contain any header file, modifying a.h does not mean that we need to recompile the source code for b.h or c.h.
991
992The cyclic dependency of header files reflects an obviously unreasonable architecture design, which can be avoided through optimization.
993
994
995### <a name="r5-2-2"></a>Rule 5.2.2 Header files should have #define guards to prevent multiple inclusion.
996To prevent header files from being included multiple times, all header files should be protected by #define. Do not use #pragma once.
997
998When defining a protection character, comply with the following rules:
9991) The protection character uses a unique name.
10002) Do not place code or comments (except for file header comments) before or after the protected part.
1001
1002Example: Assume that the timer.h file of the timer module is in the timer/include/timer.h directory. Perform the following operations to safeguard the timer.h file:
1003
1004```cpp
1005#ifndef TIMER_INCLUDE_TIMER_H
1006#define TIMER_INCLUDE_TIMER_H
1007...
1008#endif
1009```
1010
1011### <a name="r5-2-3"></a>Rule 5.2.3 It is prohibited to reference external function interfaces and variables in extern declaration mode.
1012Interfaces provided by other modules or files can be used only by including header files.
1013Using external function interfaces and variables in extern declaration mode may cause inconsistency between declarations and definitions when external interfaces are changed.
1014In addition, this kind of implicit dependency may cause architecture corruption.
1015
1016Cases that do not comply with specifications:
1017
1018// a.cpp content
1019```cpp
1020extern int Fun();   // Bad: Use external functions in extern mode.
1021
1022void Bar()
1023{
1024    int i = Fun();
1025    ...
1026}
1027```
1028
1029// b.cpp content
1030```cpp
1031int Fun()
1032{
1033    // Do something
1034}
1035```
1036Should be changed to:
1037
1038// a.cpp content
1039```cpp
1040#include "b.h"   // Good: Use the interface provided by other .cpp by including its corresponding header file.
1041
1042void Bar()
1043{
1044    int i = Fun();
1045    ...
1046}
1047```
1048
1049// b.h content
1050```cpp
1051int Fun();
1052```
1053
1054// b.cpp content
1055```cpp
1056int Fun()
1057{
1058    // Do something
1059}
1060```
1061In some scenarios, if internal functions need to be referenced with no intrusion to the code, the extern declaration mode can be used.
1062For example:
1063When performing unit testing on an internal function, you can use the extern declaration to reference the tested function.
1064When a function needs to be stubbed or patched, the function can be declared using extern.
1065
1066### <a name="r5-2-4"></a>Rule 5.2.4 Do not include header files in extern "C".
1067If a header file is included in extern "C", extern "C" may be nested. Some compilers restrict the nesting of extern "C". If there are too many nested layers, compilation errors may occur.
1068
1069When C and C++ programmings are used together and if extern "C" includes a header file, the original intent behind the header file may be hindered. For example, when the link specifications are modified incorrectly.
1070
1071For example, assume that there are two header files a.h and b.h.
1072
1073// a.h content
1074```cpp
1075...
1076#ifdef __cplusplus
1077void Foo(int);
1078#define A(value) Foo(value)
1079#else
1080void A(int)
1081#endif
1082```
1083// b.h content
1084```cpp
1085...
1086#ifdef __cplusplus
1087extern "C" {
1088#endif
1089
1090#include "a.h"
1091void B();
1092
1093#ifdef __cplusplus
1094}
1095#endif
1096```
1097
1098Using the C++ preprocessor to expand b.h, the following information is displayed:
1099```cpp
1100extern "C" {
1101    void Foo(int);
1102    void B();
1103}
1104```
1105
1106According to the author of a.h, the function Foo is a C++ free function following the "C++" link specification.
1107However, because `#include "a.h"` is placed inside `extern "C"` in b.h, the link specification of function Foo is changed incorrectly.
1108
1109Exception:
1110In the C++ compilation environment, if you want to reference the header file of pure C, the C header files should not contain `extern "C"`. The non-intrusive approach is to include the C header file in `extern "C"`.
1111
1112### <a name="a5-2-1"></a>Recommendation 5.2.1 Use `#include` instead of a forward declaration to include header files.
1113A forward declaration is for the declaration of classes, functions, and templates and is not meant for its definition.
1114
1115- Advantages:
1116  1. Forward declarations can save compilation time. Redundant `#include `statements force the compiler to expand more files and process more input.
1117  2. Forward declarations can save unnecessary recompilation time. The use of #include will force your code to be recompiled multiple times due to unrelated changes in header files.
1118- Disadvantages:
1119  1. Forward declarations hide dependency relationship. When a header file is modified, user code will skip the necessary recompilation process.
1120  2. A forward declaration may be broken by subsequent changes to the library. Forward declarations of functions and templates sometimes prevent header file developers from changing APIs. For example, widening a formal parameter type, adding a template parameter with a default value, and so on.
1121  3. Forward declaration of symbols from the namespace `std::` is seen as undefined behavior (as specified in the C++ 11 standard specification).
1122  4. Forward declaration of multiple symbols from a header file can be more verbose than simply including (#include) the header.
1123  5. Structuring code only for forward declaration (for example, using pointer members instead of object members) can make the code more complex and slower.
1124  6. It is difficult to determine whether a forward declaration or `#include` is needed. In some scenarios, replacing `#include` with a forward declaration may cause unexpected results.
1125
1126Therefore, we should avoid using forward declarations as much as possible. Instead, we use the #include statement to include a header file and ensure dependency.
1127
1128# <a name="c6"></a>6 Scopes
1129
1130## <a name="c6-1"></a> Namespaces
1131
1132### <a name="a6-1-1"></a>Recommendation 6.1.1 For code that does not need to be exported from the .cpp file, you are advised to use an unnamed namespace for encapsulation or use static to modify the variables, constants, or functions that need hiding.
1133In the C++ 2003 standard, using static to modify the external availability of functions and variables was marked as deprecated. Therefore, unnamed namespaces are the recommended method.
1134
1135Main Reasons:
11361. There are too many meanings for static in C++: static function member variable, static member function, static global variable, and static function local variable. Each of them has special processing.
11372. Static can only be used to define variables, constants, and functions that are not referenced outside the current .cpp file, while namespaces can also be used to encapsulate types.
11383. Use a namespace to control the scope instead of using both static and namespaces.
11394. Unnamed namespaces can be used to instantiate templates rather than functions modified by the static keyword.
1140
1141Do not use unnamed namespaces or static in header files.
1142
1143```cpp
1144// Foo.cpp
1145
1146namespace {
1147    const int MAX_COUNT = 20;
1148    void InternalFun(){};
1149}
1150
1151void Foo::Fun()
1152{
1153    int i = MAX_COUNT;
1154
1155    InternalFun();
1156}
1157
1158```
1159
1160### <a name="r6-1-1"></a>Rule 6.1.1 Do not use "using" to import namespace in a header file or before #include statements.
1161Note: Using "using" to import namespace will affect any subsequent code and may cause symbol conflicts.
1162Example:
1163
1164```cpp
1165// Header file a.h
1166namespace NamespaceA {
1167    int Fun(int);
1168}
1169```
1170
1171```cpp
1172// Header file b.h
1173namespace NamespaceB {
1174    int Fun(int);
1175}
1176
1177using namespace NamespaceB;
1178
1179void G()
1180{
1181    Fun(1);
1182}
1183```
1184
1185```cpp
1186// Source code a.cpp
1187#include "a.h"
1188using namespace NamespaceA;
1189#include "b.h"
1190
1191void main()
1192{
1193    G(); // "using namespace NamespaceA" before #include "b.h", will cause conflicts when calling NamespaceA::Fun and NamespaceB::Fun.
1194}
1195```
1196
1197Using "using" to import a symbol or define an alias in a header file is allowed in customized namespaces of modules, but is prohibited in the global namespace.
1198```cpp
1199// foo.h
1200
1201#include <fancy/string>
1202using fancy::string;  // Bad: It is prohibited to import symbols to the global namespace.
1203
1204namespace Foo {
1205    using fancy::string;  // Good: Symbols can be imported in customized namespaces of modules.
1206    using MyVector = fancy::vector;  // Good: In C++11, aliases can be defined in customized namespaces.
1207}
1208```
1209
1210
1211## <a name="c6-2"></a> Global Functions and Static Member Functions
1212
1213### <a name="a6-2-1"></a>Recommendation 6.2.1 Use namespaces to manage global functions. If global functions are closely tied to a class, you can use static member functions.
1214Note: Placing non-member functions in a namespace avoids polluting the global scope. Do not use "class + static member function" to simply manage global functions. If a global function is closely tied to a class, it can be used as a static member function of the class.
1215
1216If you need to define some global functions for a .cpp file, use unnamed namespaces for management.
1217```cpp
1218namespace MyNamespace {
1219    int Add(int a, int b);
1220}
1221
1222class File {
1223public:
1224    static File CreateTempFile(const std::string& fileName);
1225};
1226```
1227
1228## <a name="c6-3"></a> Global Constants and Static Member Constants
1229
1230### <a name="a6-3-1"></a>Recommendation 6.3.1 Use namespaces to manage global constants. If global constants are closely tied to a class, you can use static member constants.
1231Note: Placing global constants in a namespace avoids polluting the global scope. Do not use "class + static member constant" to simply manage global constants. If a global constant is closely tied to a class, it can be used as a static member constant of the class.
1232
1233If you need to define some global constants only for a .cpp file, use unnamed namespaces for management.
1234```cpp
1235namespace MyNamespace {
1236    const int MAX_SIZE = 100;
1237}
1238
1239class File {
1240public:
1241    static const std::string SEPARATOR;
1242};
1243```
1244
1245## <a name="c6-4"></a> Global Variables
1246
1247### <a name="a6-4-1"></a>Recommendation 6.4.1 Do not use global variables. Use the singleton pattern instead.
1248Note: Global variables can be modified and read, which results in data coupling between production code and the global variables.
1249```cpp
1250int g_counter = 0;
1251
1252// a.cpp
1253g_counter++;
1254
1255// b.cpp
1256g_counter++;
1257
1258// c.cpp
1259cout << g_counter << endl;
1260```
1261
1262Singleton
1263```cpp
1264class Counter {
1265public:
1266    static Counter& GetInstance()
1267    {
1268        static Counter counter;
1269        return counter;
1270    }  // Simple example of a singleton implementation
1271
1272    void Increase()
1273    {
1274        value_++;
1275    }
1276
1277    void Print() const
1278    {
1279        std::cout << value_ << std::endl;
1280    }
1281
1282private:
1283    Counter() : value_(0) {}
1284
1285private:
1286    int value_;
1287};
1288
1289// a.cpp
1290Counter::GetInstance().Increase();
1291
1292// b.cpp
1293Counter::GetInstance().Increase();
1294
1295// c.cpp
1296Counter::GetInstance().Print();
1297```
1298
1299After the singleton is implemented, there is a unique global instance, which can functions as a global variable. However, the singleton provides better encapsulation.
1300
1301Exception: In some cases, the scope of a global variable is contained inside a module. Multiple instances of the same global variable may exist, and each module holds one copy. In this case, a singleton cannot be used as it is limited to one instance.
1302
1303# <a name="c7"></a>7 Classes
1304
1305## <a name="c7-1"></a> Constructors, Copy/Move Constructors, Copy/Move Assignment Operators, and Destructors
1306Constructors, copy/move constructors, copy/move assignment operators, and destructors provide lifetime management methods for objects.
1307- Constructor: `X()`
1308- Copy constructor: `X(const X&)`
1309- Copy assignment operator: `operator=(const X&)`
1310- Move constructor: `X (X&&)`         *Provided in versions later than C++ 11*.
1311- Move assignment operator: `operator=(X&&)`       *Provided in versions later than C++ 11*.
1312- Destructor: `~X()`
1313
1314### <a name="r7-1-1"></a>Rule 7.1.1 The member variables of a class must be initialized explicitly.
1315Note: If a class has members but no constructor and a default constructor is defined, the compiler will automatically generate a constructor, but it will not initialize member variables. The content of each object is uncertain.
1316
1317Exception:
1318- If the member variables in a class have a default constructor, explicit initialization is not required.
1319
1320Example: The following code has no constructor, and private data members cannot be initialized:
1321```cpp
1322class Message {
1323public:
1324    void ProcessOutMsg()
1325    {
1326        //…
1327    }
1328
1329private:
1330    unsigned int msgID_;
1331    unsigned int msgLength_;
1332    unsigned char* msgBuffer_;
1333    std::string someIdentifier_;
1334};
1335
1336Message message;   // The message member is not initialized.
1337message.ProcessOutMsg();   // Potential risks exist in subsequent use.
1338
1339// Therefore, it is necessary to define a default constructor as follows:
1340class Message {
1341public:
1342    Message() : msgID_(0), msgLength_(0), msgBuffer_(NULL)
1343    {
1344    }
1345
1346    void ProcessOutMsg()
1347    {
1348        // …
1349    }
1350
1351private:
1352    unsigned int msgID_;
1353    unsigned int msgLength_;
1354    unsigned char* msgBuffer_;
1355    std::string someIdentifier; // The member variable has a default constructor. Therefore, explicit initialization is not required.
1356};
1357```
1358
1359### <a name="a7-1-1"></a>Recommendation 7.1.1 Initialization during declaration (C++ 11) and initialization using the constructor initialization list are preferred for member variables.
1360Note: Initialization during declaration (C++11) is preferred because initialized values of member variables can be easily understood. If initialized values of certain member variables are relevant to constructors, or C++ 11 is not supported, the constructor initialization list is used preferentially to initialize these member variables. Compared with the assignment statements in constructors, code of the constructor initialization list is simpler and has higher performance, and can be used to initialize constant and reference members.
1361
1362```cpp
1363class Message {
1364public:
1365    Message() : msgLength(0) {  // Good: The constructor initialization list is preferred.
1366    {
1367        msgBuffer = NULL;     // Bad: Values cannot be assigned in constructors.
1368    }
1369
1370private:
1371    unsigned int msgID{0};  // Good: Used in C++11.
1372    unsigned int msgLength_;
1373    unsigned char* msgBuffer_;
1374};
1375```
1376
1377### <a name="r7-1-2"></a>Rule 7.1.2 Declare single-parameter constructors as explicit to prevent implicit conversion.
1378Note: If a single-parameter constructor is not declared as explicit, it will become an implicit conversion function.
1379Example:
1380
1381```cpp
1382class Foo {
1383public:
1384    explicit Foo(const string& name): name_(name)
1385    {
1386    }
1387private:
1388    string name_;
1389};
1390
1391
1392void ProcessFoo(const Foo& foo){}
1393
1394int main(void)
1395{
1396    std::string test = "test";
1397    ProcessFoo(test);  // Compiling failed.
1398    return 0;
1399}
1400```
1401
1402The preceding code fails to be compiled because the parameter required by `ProcessFoo` is of the Foo type, which mismatch with the input string type.
1403
1404If the explicit keyword of the Foo constructor is removed, implicit conversion is triggered and a temporary Foo object is generated when `ProcessFoo` is called with the string parameter. Usually, this implicit conversion is confusing and bugs are apt to be hidden, due to unexpected type conversion. Therefore, single-parameter constructors require explicit declaration.
1405
1406### <a name="r7-1-3"></a>Rule 7.1.3 If copy/move constructors and copy/move assignment operators are not needed, clearly prohibit them.
1407Note: If users do not define it, the compiler will generate copy constructors and copy assignment operators, move constructors and move assignment operators (move semantic functions will be available in versions later than C++ 11).
1408If we do not use copy constructors or copy assignment operators, explicitly delete them.
1409
14101. Set copy constructors or copy assignment operators to private and do not implement them.
1411```cpp
1412class Foo {
1413private:
1414    Foo(const Foo&);
1415    Foo& operator=(const Foo&);
1416};
1417```
14182. Use delete provided by C++ 11. For details, see Rule 10.1.3 in chapter 10 Modern C++ Features.
1419
1420### <a name="r7-1-4"></a>Rule 7.1.4 Copy constructors and copy assignment operators should be implemented or forbidden together.
1421Both copy constructors and copy assignment operators provide copy semantics. They should be implemented or hidden together.
1422
1423```cpp
1424// The copy constructor and the copy assignment operator are implemented together.
1425class Foo {
1426public:
1427    ...
1428    Foo(const Foo&);
1429    Foo& operator=(const Foo&);
1430    ...
1431};
1432
1433// The copy constructor and the copy assignment operator are both set to default, as supported by C++ 11.
1434class Foo {
1435public:
1436    Foo(const Foo&) = default;
1437    Foo& operator=(const Foo&) = default;
1438};
1439
1440// The copy constructor and the copy assignment operator are hidden together. You should use the delete keyword if C++11 features are available.
1441class Foo {
1442private:
1443    Foo(const Foo&);
1444    Foo& operator=(const Foo&);
1445};
1446```
1447
1448### <a name="r7-1-5"></a>Rule 7.1.5 Move constructors and move assignment operators should be implemented or hidden together.
1449The move operation is added in C++ 11. If a class is required to support the move operation, move constructors and move assignment operators need to be implemented.
1450
1451Both move constructors and move assignment operators provide move semantics. They should be implemented or hidden together.
1452```cpp
1453// The copy constructor and the copy assignment operator are implemented together.
1454class Foo {
1455public:
1456    ...
1457    Foo(Foo&&);
1458    Foo& operator=(Foo&&);
1459    ...
1460};
1461
1462// The copy constructor and the copy assignment operator are both set to default, as supported by C++ 11.
1463class Foo {
1464public:
1465    Foo(Foo&&) = default;
1466    Foo& operator=(Foo&&) = default;
1467};
1468
1469// The copy constructor and the copy assignment operator are hidden together. You should use the delete keyword if C++11 features are available.
1470class Foo {
1471public:
1472    Foo(Foo&&) = delete;
1473    Foo& operator=(Foo&&) = delete;
1474};
1475```
1476
1477### <a name="r7-1-6"></a>Rule 7.1.6 It is prohibited to call virtual functions in constructors and destructors.
1478Note: Calling a virtual function of the current object in a constructor or destructor will cause behaviors of non-polymorphism.
1479In C++, a base class constructs only one complete object at a time.
1480
1481Example: Base indicates the base class, and Sub indicates the derived class.
1482```cpp
1483class Base {
1484public:
1485    Base();
1486    virtual void Log() = 0;    // Different derived classes call different log files.
1487};
1488
1489Base::Base()         // Base class constructor
1490{
1491    Log();           // Call the virtual function log.
1492}
1493
1494class Sub : public Base {
1495public:
1496    virtual void Log();
1497};
1498```
1499
1500When running the following statement:
1501`Sub sub;`
1502The constructor of the derived class is executed first. However, the constructor of the base class is called first. Because the constructor of the base class calls the virtual function log, the log is in the base class version. The derived class is constructed only after the base class is constructed. As a result, behaviors of non-polymorphism are caused.
1503This also applies to destructors.
1504
1505
1506## <a name="c7-2"></a> Inheritance
1507
1508### <a name="r7-2-1"></a>Rule 7.2.1 Destructors of a base class should be declared as virtual.
1509Note: Destructors of the derived class can be called during polymorphism invocation only when destructors of the base class are virtual.
1510
1511Example: There will be memory leak if destructors of the base class are not declared as virtual.
1512```cpp
1513class Base {
1514public:
1515    virtual std::string getVersion() = 0;
1516
1517    ~Base()
1518    {
1519        std::cout << "~Base" << std::endl;
1520    }
1521};
1522```
1523
1524```cpp
1525class Sub : public Base {
1526public:
1527    Sub() : numbers_(NULL)
1528    {
1529    }
1530
1531    ~Sub()
1532    {
1533        delete[] numbers_;
1534        std::cout << "~Sub" << std::endl;
1535    }
1536
1537    int Init()
1538    {
1539        const size_t numberCount = 100;
1540        numbers_ = new (std::nothrow) int[numberCount];
1541        if (numbers_ == NULL) {
1542            return -1;
1543        }
1544
1545        ...
1546    }
1547
1548    std::string getVersion()
1549    {
1550        return std::string("hello!");
1551    }
1552private:
1553    int* numbers_;
1554};
1555```
1556
1557```cpp
1558int main(int argc, char* args[])
1559{
1560    Base* b = new Sub();
1561
1562    delete b;
1563    return 0;
1564}
1565```
1566Because destructors of the base class are not declared as virtual, only destructors of the base class are called when an object is destroyed. Destructors of the derived class Sub are not called. As a result, a memory leak occurs.
1567
1568
1569### <a name="r7-2-2"></a>Rule 7.2.2 Do not use default parameter values for virtual functions.
1570Note: In C++, virtual functions are dynamically bound, but the default parameters of functions are statically bound during compilation. This means that the function you finally execute is a virtual function that is defined in the derived class but uses the default parameter value in the base class. To avoid confusion and other problems caused by inconsistent default parameter declarations during overriding of virtual functions, it is prohibited to declare default parameter values for all virtual functions.
1571Example: The default value of parameter "text" of the virtual function "Display" is determined at compilation time instead of runtime, which does not fit with polymorphism.
1572```cpp
1573class Base {
1574public:
1575    virtual void Display(const std::string& text = "Base!")
1576    {
1577        std::cout << text << std::endl;
1578    }
1579
1580    virtual ~Base(){}
1581};
1582
1583class Sub : public Base {
1584public:
1585    virtual void Display(const std::string& text  = "Sub!")
1586    {
1587        std::cout << text << std::endl;
1588    }
1589
1590    virtual ~Sub(){}
1591};
1592
1593int main()
1594{
1595    Base* base = new Sub();
1596    Sub* sub = new Sub();
1597
1598    ...
1599
1600    base->Display();  // The program output is as follows: Base! The expected output is as follows: Sub!
1601    sub->Display();   // The program output is as follows: Sub!
1602
1603    delete base;
1604    delete sub;
1605    return 0;
1606};
1607```
1608
1609### <a name="r7-2-3"></a>Rule 7.2.3 Do not redefine inherited non-virtual functions.
1610Note: Non-virtual functions cannot be dynamically bound (only virtual functions can be dynamically bound). You can obtain the correct result by operating on the pointer of the base class.
1611
1612Example:
1613```cpp
1614class Base {
1615public:
1616    void Fun();
1617};
1618
1619class Sub : public Base {
1620public:
1621    void Fun();
1622};
1623
1624Sub* sub = new Sub();
1625Base* base = sub;
1626
1627sub->Fun();    // Call Fun of the derived class.
1628base->Fun();   // Call Fun of the base class.
1629//...
1630
1631```
1632
1633## <a name="c7-3"></a> Multiple Inheritance
1634In the actual development process, multiple inheritance is seldom used because the following typical problems may occur:
16351. Data duplication and name ambiguity caused by "diamond" inheritance. C++ introduces virtual inheritance to solve these problems.
16362. In addition to "diamond" inheritance, names of multiple base classes may also conflict with each other, resulting in name ambiguity.
16373. If a derived class needs to be extended or needs to override methods of multiple base classes, the responsibilities of the derived classes are unclear and semantics are muddled.
16384. Compared with delegation, inheritance is seen as white box reuse, that is, a derived class can access the protected members of the base class, which leads to more coupling. Multiple inheritance, due to the coupling of multiple base classes, leads to even more coupling.
1639
1640Multiple inheritance has the following advantages:
1641Multiple inheritance provides a simpler method for assembling and reusing multiple interfaces or classes.
1642
1643Therefore, multiple inheritance can be used only in the following cases:
1644
1645### <a name="a7-3-1"></a>Recommendation 7.3.1 Use multiple inheritance to implement interface separation and multi-role combination.
1646If a class requires multiple interfaces, combine multiple separated interfaces by using multiple inheritance. This is similar to the Traits mixin of the Scala language.
1647
1648```cpp
1649class Role1 {};
1650class Role2 {};
1651class Role3 {};
1652
1653class Object1 : public Role1, public Role2 {
1654    // ...
1655};
1656
1657class Object2 : public Role2, public Role3 {
1658    // ...
1659};
1660
1661```
1662
1663The C++ standard library has a similar implementation example:
1664```cpp
1665class basic_istream {};
1666class basic_ostream {};
1667
1668class basic_iostream : public basic_istream, public basic_ostream {
1669
1670};
1671```
1672
1673## <a name="c7-4"></a> Overloading
1674
1675Overload operators should be used when there are sufficient reasons, and they do not change the original perception of the operators. For example, do not use the plus sign (+) to perform subtraction.
1676Operator overloading can make code more intuitive but has some disadvantages:
1677- It is often mistaken that the operation is as fast as a built-in operator, which has no performance degradation.
1678- There is no naming to aid debugging. It is more convenient to search by function name than by operator.
1679- Overloading operators can cause confusion if behavior definitions are not intuitive (for example, if the "+" operator is used for subtraction).
1680- The implicit conversion caused by the overloading of assignment operators may lead to entrenched bugs. Functions such as Equals () and CopyFrom () can be defined to replace the = and == operators.
1681
1682
1683
1684# <a name="c8"></a> 8 Functions
1685## <a name="c8-1"></a>Function Design
1686### <a name="r8-1-1"></a>Rule 8.1.1 Avoid long functions and ensure that each function contains no more than 50 lines (non-null and non-comment).
1687A function should be displayed on one screen (no longer than 50 lines). It should do only one thing, and do it well.
1688
1689Long functions often mean that the functions are too complex to implement in more than one function, or overly detailed but not further abstracted.
1690
1691Exception: Some algorithms may be longer than 50 lines due to algorithm convergence and functional comprehensiveness.
1692
1693Even if a long function works very well now, once someone modifies it, new problems may occur. It might even cause bugs that are difficult to find.
1694It is recommended that you split a long function into several functions that are simpler and easier to manage, facilitating comprehension and modification.
1695
1696## <a name="c8-2"></a>Inline Functions
1697
1698###  <a name="a8-2-1"></a>Recommendation 8.2.1 An inline function cannot exceed 10 lines.
1699**Note**: An inline function has the same characteristics of a normal function. The difference between an inline function and a normal function lies in the processing of function calls. When a general function is called, the program execution right is transferred to the called function, and then returned to the function that calls it. When an inline function is called, the invocation expression is replaced with an inline function body.
1700
1701Inline functions are only suitable for small functions with only 1-10 lines. For a large function that contains many statements, the function call and return overheads are relatively trivial and do not need the help of an inline function. Most compilers may abandon the inline mode and use the common method to call the function.
1702
1703If an inline function contains complex control structures, such as loop, branch (switch), and try-catch statements, the compiler may regard the function as a common function.
1704**Virtual functions and recursive functions cannot be used as inline functions**.
1705
1706## <a name="c8-3"></a> Function Parameters
1707
1708### <a name="a8-3-1"></a>Recommendation 8.3.1 Use a reference instead of a pointer for function parameters.
1709
1710**Note**: A reference is more secure than a pointer because it is not empty and does not point to other targets. Using a reference stops the need to check for illegal null pointers.
1711
1712If a product is being developed for an older platform, the processing used by the old platform is preferred.
1713Use const to avoid parameter modification, so that readers can clearly know that a parameter is not going to be modified. This greatly enhances code readability.
1714
1715Exception: When the input parameter is an array with an unknown compile-time length, you can use a pointer instead of a reference.
1716
1717### <a name="a8-3-2"></a>Recommendation 8.3.2 Use strongly typed parameters. Do not use void*.
1718While different languages have their own views on strong typing and weak typing, it is generally believed that C and C++ are strongly typed languages. Since we use such a strongly typed language, we should keep to this style.
1719An advantage of this is the compiler can find type mismatch problems at the compilation stage.
1720
1721Using strong typing helps the compiler find more errors for us. Pay attention to the usage of the FooListAddNode function in the following code:
1722```cpp
1723struct FooNode {
1724    struct List link;
1725    int foo;
1726};
1727
1728struct BarNode {
1729    struct List link;
1730    int bar;
1731}
1732
1733void FooListAddNode(void *node) // Bad: Here, the void * type is used to transfer parameters.
1734{
1735    FooNode *foo = (FooNode *)node;
1736    ListAppend(&g_FooList, &foo->link);
1737}
1738
1739void MakeTheList()
1740{
1741    FooNode *foo = NULL;
1742    BarNode *bar = NULL;
1743    ...
1744
1745    FooListAddNode(bar);        // Wrong: In this example, the foo parameter was supposed to be transferred, but the bar parameter is accidentally transferred instead. However, no error is reported.
1746}
1747```
1748
17491. You can use a template function to change the parameter type.
17502. A base class pointer can be used to implement this according to polymorphism.
1751
1752### <a name="a8-3-3"></a>Recommendation 8.3.3 A function can have a maximum of five parameters.
1753If a function has too many parameters, it is apt to be affected by external changes, and therefore maintenance is affected. Too many function parameters will also increase the testing workload.
1754
1755If a function has more than five parameters, you can:
1756- Split the function.
1757- Combine related parameters into a struct.
1758
1759# <a name="c9"></a> 9 Other C++ Features
1760
1761## <a name="c9-1"></a> Constants and Initialization
1762
1763Unchanged values are easier to understand, trace, and analyze. Therefore, use constants instead of variables as much as possible. When defining values, use const as a default.
1764
1765### <a name="r9-1-1"></a>Rule 9.1.1 Do not use macros to replace constants.
1766
1767**Note**: Macros are a simple text replacement that is completed in the preprocessing phase. When an error is reported, the corresponding value is reported. During tracing and debugging, the value is also displayed instead of the macro name. A macro does not support type checking and is insecure. A macro has no scope.
1768
1769```cpp
1770#define MAX_MSISDN_LEN 20    // Bad
1771
1772// Use const in C++.
1773const int MAX_MSISDN_LEN = 20; // Good
1774
1775// In versions later than C++ 11, constexpr can be used.
1776constexpr int MAX_MSISDN_LEN = 20;
1777```
1778
1779###  <a name="a9-1-1"></a>Recommendation 9.1.1 A group of related integer constants must be defined as an enumeration.
1780
1781**Note**: Enumerations are more secure than `#define` or `const int`. The compiler checks whether a parameter value is within the enumerated value range to avoid errors.
1782
1783```cpp
1784// Good example:
1785enum Week {
1786    SUNDAY,
1787    MONDAY,
1788    TUESDAY,
1789    WEDNESDAY,
1790    THURSDAY,
1791    FRIDAY,
1792    SATURDAY
1793};
1794
1795enum Color {
1796    RED,
1797    BLACK,
1798    BLUE
1799};
1800
1801void ColorizeCalendar(Week today, Color color);
1802
1803ColorizeCalendar(BLUE, SUNDAY); // Compilation error. The parameter type is incorrect.
1804
1805// Bad example:
1806const int SUNDAY = 0;
1807const int MONDAY = 1;
1808
1809const int BLACK  = 0;
1810const int BLUE   = 1;
1811
1812bool ColorizeCalendar(int today, int color);
1813ColorizeCalendar(BLUE, SUNDAY); // No error is reported.
1814```
1815
1816When an enumeration value needs to correspond to a specific value, explicit value assignment is required during declaration. Otherwise, do not assign explicit values. This will prevent repeated assignment and reduce the maintenance workload (when adding and deleting members).
1817
1818```cpp
1819// Good example: Device ID defined in the S protocol. It is used to identify a device type.
1820enum DeviceType {
1821    DEV_UNKNOWN = -1,
1822    DEV_DSMP = 0,
1823    DEV_ISMG = 1,
1824    DEV_WAPPORTAL = 2
1825};
1826```
1827
1828Do not assign explicit values when enumeration is used internally, and only for classification.
1829
1830```cpp
1831// Good example: Enumeration definition is used to identify session status in a program.
1832enum SessionState {
1833    INIT,
1834    CLOSED,
1835    WAITING_FOR_RESPONSE
1836};
1837```
1838
1839Try to avoid repeating enumeration values. If it is required, use the already defined enumeration values instead.
1840
1841```cpp
1842enum RTCPType {
1843    RTCP_SR = 200,
1844    RTCP_MIN_TYPE = RTCP_SR,
1845    RTCP_RR    = 201,
1846    RTCP_SDES  = 202,
1847    RTCP_BYE   = 203,
1848    RTCP_APP   = 204,
1849    RTCP_RTPFB = 205,
1850    RTCP_PSFB  = 206,
1851    RTCP_XR  = 207,
1852    RTCP_RSI = 208,
1853    RTCP_PUBPORTS = 209,
1854    RTCP_MAX_TYPE = RTCP_PUBPORTS
1855};
1856```
1857
1858### <a name="r9-1-2"></a>Rule 9.1.2 Magic numbers cannot be used.
1859So-called magic numbers are numbers that are unintelligible and difficult to understand.
1860
1861Some numbers can be understood based on context.
1862For example, the number 12 varies in different contexts.
1863type = 12; is not intelligible (and a magic number), but `month = year * 12`; can be understood, so we wouldn't really class this as a magic number.
1864The number 0 is often seen as a magic number. For example, `status = 0`; cannot truly express any status information.
1865
1866Solution:
1867Comments can be added for numbers that are used locally.
1868For the numbers that are used multiple times, you must define them as constants and give them descriptive names.
1869
1870The following cases are forbidden:
1871No symbol is used to explain the meaning of a number, for example, ` const int ZERO = 0`.
1872The symbol name limits the value. For example, for example, `const int XX_TIMER_INTERVAL_300MS = 300`. Use `XX_TIMER_INTERVAL_MS` instead.
1873
1874### <a name="r9-1-3"></a>Rule 9.1.3 Ensure that a constant has only one responsibility.
1875
1876**Note**: A constant is used for only one specific function, that is, a constant cannot be used for multiple purposes.
1877
1878```cpp
1879// Good example: For protocol A and protocol B, the length of the MSISDN is 20.
1880const unsigned int A_MAX_MSISDN_LEN = 20;
1881const unsigned int B_MAX_MSISDN_LEN = 20;
1882
1883// Using different namespaces:
1884namespace Namespace1 {
1885    const unsigned int MAX_MSISDN_LEN = 20;
1886}
1887
1888namespace Namespace2 {
1889    const unsigned int MAX_MSISDN_LEN = 20;
1890}
1891```
1892
1893### <a name="r9-1-4"></a>Rule 9.1.4 Do not use memcpy_s or memset_s to initialize non-POD objects.
1894
1895**Note**: `POD` is short for `Plain Old Data`, which is a concept introduced in the C++ 98 standard (ISO/IEC 14882, first edition, 1998-09-01). The `POD` types include the original types and aggregate types such as `int`, `char`, `float`, `double`, `enumeration`, `void`, and pointer. Encapsulation and object-oriented features cannot be used (for example, user-defined constructors, assignment operators, destructors, base classes, and virtual functions).
1896
1897For non-POD classes, such as class objects of non-aggregate types, virtual functions may exist. Memory layout is uncertain, and is related to the compiler. Misuse of memory copies may cause serious problems.
1898
1899Even if a class of the aggregate type is directly copied and compared, and any functions hiding information or protecting data are destroyed, the `memcpy_s` and `memset_s` operations are not recommended.
1900
1901For details about the POD type, see the appendix.
1902
1903### <a name="a9-1-2"></a>Recommendation 9.1.2 Declare and initialize variables only when they are used.
1904
1905**Note**: It is a common low-level programming error that a variable is not assigned an initial value before being used. Declaring and initializing a variable just before using it will prevent this.
1906
1907If all variables are declared at the beginning of a function before they are used, their scope covers the entire function, which may lead to the following problems:
1908* The program may become difficult to understand and maintain. The definition and use of variables are separated.
1909* These variables are difficult to initialize properly. At the beginning of a function, there is often insufficient information for variable initialization, and a default null value (such as 0) is often assigned as the initial value. If a variable is used before it is assigned a valid value, it will also cause errors.
1910
1911Following the minimization principle of variable scopes and the principle of proximity declaration will make it easier to read code and understand variable types and initial values. In particular, use initialization to replace declaration and then assign values.
1912
1913```cpp
1914// Bad example: Declaration is separated from initialization.
1915string name;        // The variable is not initialized in the declaration, and a default constructor is called.
1916name = "zhangsan";  // An assignment operator is called again. Declaration is separate from definition, which is difficult to understand.
1917
1918// Good example: Declaration and initialization are together, and easy to understand.
1919string name("zhangsan");  // Invoke a constructor.
1920```
1921
1922
1923## <a name="c9-2"></a> Expressions
1924### <a name="r9-2-1"></a>Rule 9.2.1 A variable cannot be referenced again if it is contained in an increment or decrement operation in an expression.
1925In an expression where the increment or decrement operations are performed on a variable, the variable cannot be referenced again. The result of a second referencing is not explicitly defined in C++ standards. The results in different compilers or different versions of a compiler may be different.
1926Therefore, it is recommended that an undefined operation sequence not be assumed.
1927
1928Note that the problem of operation sequence cannot be solved by using parentheses because this is not a priority problem.
1929
1930Example:
1931```cpp
1932x = b[i] + i++; // Bad: Whether the position of b[i] is before or after the i++ is unclear.
1933```
1934The increment or decrement operation should be placed in a single line:
1935```cpp
1936x = b[i] + i;
1937i++;            // Good: i++ is placed in a single line.
1938```
1939
1940Function parameter
1941```cpp
1942Func(i++, i);   // Bad: Whether the increment operation happens for the second parameter is unclear
1943```
1944
1945Good example:
1946```cpp
1947i++;            // Good: i++ is placed in a single line.
1948x = Func(i, i);
1949```
1950
1951### <a name="r9-2-2"></a>Rule 9.2.2 A switch statement must have a default branch.
1952In most cases, a switch statement requires a default branch to ensure that there is a default action when the case tag is missing for a processed value.
1953
1954Exception:
1955If the switch condition variables are enumerated and the case branch covers all values, the default branch is redundant.
1956Because modern compilers can check which case branches are missing in the switch statement and provide an advanced warning.
1957
1958```cpp
1959enum Color {
1960    RED = 0,
1961    BLUE
1962};
1963
1964// The switch condition variables are enumerated. Therefore, you do not need to add a default branch.
1965switch (color) {
1966    case RED:
1967        DoRedThing();
1968        break;
1969    case BLUE:
1970        DoBlueThing();
1971        ...
1972        break;
1973}
1974```
1975
1976### <a name="a9-2-1"></a>Recommendation 9.2.1 When comparing expressions, follow the principle that the left side tends to change and the right side tends to remain unchanged.
1977When a variable is compared with a constant, placing the constant on the left, for example, if (MAX == v), does not comply with standard reading habits  and is more difficult to understand.
1978The constant should be placed on the right. The expression is written as follows:
1979```cpp
1980if (value == MAX) {
1981
1982}
1983
1984if (value < MAX) {
1985
1986}
1987```
1988There are special cases: for example, if the expression `if (MIN < value && value < MAX)` is used to describe a range, the first half, as a constant, should be placed on the left.
1989
1990You do not need to worry about writing '==' as '=' because a compilation alarm will be generated for `if (value = MAX)` and an error will be reported by other static check tools. Use these tools to solve such writing errors and ensure that that code is readable.
1991
1992### <a name="a9-2-2"></a>Recommendation 9.2.2 Use parentheses to specify the operator precedence.
1993Use parentheses to specify the operator precedence. This will prevent program errors due to the inconsistency between default priority and the intended design. At the same time, it makes the code clearer and more readable. However, too many parentheses muddy the code, reducing readability. The following is a recommendation on their correct usage.
1994
1995- For binary and ternary operators, if multiple operators are involved, parentheses should be used.
1996```cpp
1997x = a + b + c;        /* The operator does not change, and thus parentheses are not required. */
1998x = Foo(a + b, c);     /* The operator does not change, and thus parentheses are not required. */
1999x = 1 << (2 + 3);      /* More than one operator is used and thus parentheses are required. */
2000x = a + (b / 5);       /* More than one operator is used and thus parentheses are required. */
2001x = (a == b) ? a : (a – b);    /* More than one operator is used and thus parentheses are required. */
2002```
2003
2004
2005## <a name="c9-3"></a> Type Casting
2006
2007Do not use type branches to customize behaviors. Type branch customization behavior is prone to errors and is an obvious sign of attempting to compile C code using C++. This is very inflexible technology. If you forget to modify all branches when adding a new type to a compiler, you will not be notified. Use templates and virtual functions to let the type define itself rather than letting the calling side determine behavior.
2008
2009It is recommended that type casting be avoided. We should consider the data type in the code design instead of overusing type casting to solve type conflicts. When designing a basic type, consider the following:
2010- Whether it is unsigned or signed.
2011- Is it suitable for float or double?
2012- Should you use int8, int16, int32, or int64 bit lengths?
2013
2014However, we cannot prohibit the use of type casting because the C++ language is a machine-oriented programming language, involving pointer addresses, and we interact with various third-party or underlying APIs. Their type design may not be reasonable and type casting tends to occur in the adaptation process.
2015
2016Exception: When calling a function, if we do not want to process the result of the function, first consider whether this is your best choice. If you do not want to process the return value of the function, cast it to void.
2017
2018### <a name="r9-3-1"></a>Rule 9.3.1 If type casting is required, use the type casting provided by the C++ instead of the C style.
2019
2020**Note**:
2021
2022The type casting provided by C++ is more targeted, easy to read, and more secure than the C style. C++ provides the following types of casting:
2023- Type casting:
20241. `dynamic_cast`: Used to inherit the downstream transformation of the system. `dynamic_cast` has the type check function. Design the base class and derived class to avoid using dynamic_cast for casting.
20252. `static_cast`: Similar to the C style casting, which can be used to convert a value, or to convert the pointer or reference of a derived class into a base class pointer or reference. This casting is often used to eliminate type ambiguity brought on by multiple inheritance, which is relatively safe. If it is a pure arithmetic conversion, use the braces as stated in the following text.
20263. `reinterpret_cast`: Used to convert irrelevant types. `reinterpret_cast` forces the compiler to reinterpret the memory of a certain type of objects into another type, which is an unsafe conversion. It is recommended that `reinterpret_cast` be used as little as possible.
20274. `const_cast`: Used to remove the `const` attribute of an object so that the object can be modified. You are advised to use `const_cast` as little as possible.
2028
2029- Arithmetic conversion: (Supported by C++ 11 and later versions)
2030  If the type information is not lost, for example, the casting from float to double, or from int32 to int64, the braces syntax is recommended.
2031```cpp
2032  double d{ someFloat };
2033  int64_t i{ someInt32 };
2034```
2035
2036### <a name="a9-3-1"></a>Recommendation 9.3.1 Avoid using `dynamic_cast`.
20371. `dynamic_cast` depends on the RTTI of C++ so that the programmer can identify the type of the object in C++ at run time.
20382. `dynamic_cast` indicates that a problem has occurred in the design of the base class and derived class.The derived class destroys the contract of the base class and it is necessary to use `dynamic_cast` to convert the class to a subclass for special processing. In this case, it is more desirable to improve the design of the class, instead of using `dynamic_cast` to solve the problem.
2039
2040### <a name="a9-3-2"></a>Recommendation 9.3.2 Avoid using `reinterpret_cast`.
2041
2042**Note**: `reinterpret_cast` is used to convert irrelevant types. Trying to use `reinterpret_cast` to force a type to another type destroys the security and reliability of the type and is an insecure casting method. Avoid casting between completely different types.
2043
2044### <a name="a9-3-3"></a>Recommendation 9.3.3 Avoid using `const_cast`.
2045
2046**Note**: The `const_cast` command is used to remove the `const`  and `volatile` properties of an object.
2047
2048The action of using a pointer or reference after the const_cast conversion to modify the const property of an object is undefined.
2049
2050```cpp
2051// Bad example:
2052const int i = 1024;
2053int* p = const_cast<int*>(&i);
2054*p = 2048;      // The action is undefined.
2055```
2056
2057```cpp
2058// Bad example:
2059class Foo {
2060public:
2061    Foo() : i(3) {}
2062
2063    void Fun(int v)
2064    {
2065        i = v;
2066    }
2067
2068private:
2069    int i;
2070};
2071
2072int main(void)
2073{
2074    const Foo f;
2075    Foo* p = const_cast<Foo*>(&f);
2076    p->Fun(8);  // The action is undefined.
2077}
2078
2079```
2080
2081
2082## <a name="c9-4"></a>Resource Allocation and Release
2083
2084### <a name="r9-4-1"></a>Rule 9.4.1 When a single object is released, delete is used. When an array object is released, delete [] is used.
2085Note: To delete a single object, use delete; to delete an array object, use delete []. The reasons are as follows:
2086
2087- new: Apply for memory from the system and call the corresponding constructor to initialize an object.
2088- new[n]: Apply for memory for n objects and call the constructor n times for each object to initialize them.
2089- delete: Call the corresponding destructor first and release the memory of an object.
2090- delete[]: Call the corresponding destructor for each object and release their memory.
2091
2092If the usage of new and delete does not match this format, the results are unknown. For a non-class type, new and delete will not call the constructor or destructor.
2093
2094Bad example:
2095```cpp
2096const int MAX_ARRAY_SIZE = 100;
2097int* numberArray = new int[MAX_ARRAY_SIZE];
2098...
2099delete numberArray;
2100numberArray = NULL;
2101```
2102
2103Good example:
2104```cpp
2105const int MAX_ARRAY_SIZE = 100;
2106int* numberArray = new int[MAX_ARRAY_SIZE];
2107...
2108delete[] numberArray;
2109numberArray = NULL;
2110```
2111
2112### <a name="a9-4-1"></a>Recommendation 9.4.1 Use the RAII feature to trace dynamic allocation.
2113
2114Note: RAII is an acronym for Resource Acquisition Is Initialization. It is a simple technology that controls program resources (such as memory, file handle, network connections, and mutexes) by using the object lifecycle.
2115
2116The common practice is as follows: When the object is constructed, the resource is obtained, and the access to the resource is controlled so that the resource is always valid in the life cycle of the object. Finally, the resource is released when the object is destructed. This approach has two advantages:
2117- We do not need to explicitly release resources.
2118- The resources required by the object are always valid throughout the lifecycle of the object. This way, you do not need to check the validity of the resources, which simplifies logic and improves efficiency.
2119
2120
2121In the following example, RAII removes the need for explicit release of mutex resources.
2122
2123```cpp
2124class LockGuard {
2125public:
2126    LockGuard(const LockType& lockType): lock_(lockType)
2127    {
2128        lock_.Aquire();
2129    }
2130
2131    ~LockGuard()
2132    {
2133        lock_.Relase();
2134    }
2135
2136private:
2137    LockType lock_;
2138};
2139
2140
2141bool Update()
2142{
2143    LockGuard lockGuard(mutex);
2144    if (...) {
2145        return false;
2146    } else {
2147        // Data operations
2148    }
2149
2150    return true;
2151}
2152```
2153
2154## <a name="c9-5"></a>Standard Template Library
2155
2156The standard template library (STL) varies between products. The following table lists some basic rules and suggestions for each team.
2157
2158### <a name="r9-5-1"></a>Rule 9.5.1 Do not save the pointer returned by c_str () of std::string.
2159
2160Note: The C++ standard does not specify that the string::c_str () pointer is permanently valid. Therefore, the STL implementation used can return a temporary storage area and release it quickly when calling string::c_str (). Therefore, to ensure the portability of the program, do not save the result of string::c_str (). Instead, call it directly.
2161
2162Example:
2163
2164```cpp
2165void Fun1()
2166{
2167    std::string name = "demo";
2168    const char* text = name.c_str(); // After the expression ends, the life cycle of name is still in use and the pointer is valid.
2169
2170    // If a non-const member function (such as operator[] and begin()) of the string type is invoked and the string is modified,
2171    // The text may become unavailable or may not be the original string.
2172    name = "test";
2173    name[1] = '2';
2174
2175    // When the text pointer is used next time, the string is no longer "demo".
2176}
2177
2178void Fun2()
2179{
2180    std::string name = "demo";
2181    std::string test = "test";
2182    const char* text = (name + test).c_str(); // After the expression ends, the temporary object generated by the + operator may be destroyed, and the pointer may be invalid.
2183
2184    // When the text pointer is used next time, it no longer points to the valid memory space.
2185}
2186```
2187Exception: In rare cases where high performance coding is required , you can temporarily save the pointer returned by string::c_str() to match the existing functions which support only the input parameters of the const char* type. However, you should ensure that the lifecycle of the string object is longer than that of the saved pointer, and that the string object is not modified within the lifecycle of the saved pointer.
2188
2189
2190### <a name="a9-5-1"></a>Recommendation 9.5.1 Use std::string instead of char*.
2191
2192Note: Using string instead of `char*` has the following advantages:
21931. There is no need to consider the null character ’\0’at the end.
21942. You can directly use operators such as `+`,  `=`, and `==`, and other character and string operation functions.
21953. There is no need to consider memory allocation operations.This helps avoid explicit usage of `new` and `delete` and the resulting errors.
2196
2197Note that in some STL implementations, string is based on the copy-on-write policy, which causes two problems. One is that the copy-on-write policy of some versions does not implement thread security, and the program breaks down in multi-threaded environments. Second, dangling pointers may be caused when a dynamic link library transfers the string based on the copy-on-write policy, due to the fact that reference count cannot be reduced when the library is unloaded. Therefore, it is important to select a reliable STL implementation to ensure the stability of the program.
2198
2199Exception:
2200When an API of a system or other third-party library is called, only `char*` can be used for defined interfaces. However, before calling the interfaces, you can use string. When calling the interfaces, you can use `string::c_str()` to obtain the character pointer.
2201When a character array is allocated as a buffer on the stack, you can directly define the character array without using string or containers such as `vector<char>`.
2202
2203### <a name="r9-5-2"></a>Rule 9.5.2 Do not use auto_ptr.
2204Note: The `std::auto_ptr` in the STL library has an implicit ownership transfer behavior. The code is as follows:
2205```cpp
2206auto_ptr<T> p1(new T);
2207auto_ptr<T> p2 = p1;
2208```
2209After the second line of statements is executed, p1 does not point to the object allocated in line 1 and becomes `NULL`. Therefore, `auto_ptr` cannot be placed in any standard containers.
2210This ownership transfer behavior is not expected. In scenarios where ownership must be transferred, implicit transfer should not be used. This often requires the programmer to keep extra attention on code that uses `auto_ptr`, otherwise access to a null pointer will occur.
2211There are two common scenarios for using auto_ptr . One is to transfer it as a smart pointer to outside the function that generates the auto_ptr , and the other is to use auto_ptr as the RAII management class. Resources are automatically released when the lifecycle of auto_ptr expires.
2212In the first scenario, you can use std::shared_ptr instead.
2213In the second scenario, you can use std::unique_ptr in the C++ 11 standard. std::unique_ptr is a substitute for std::auto_ptr and supports explicit ownership transfer.
2214
2215Exception:
2216Before the C++ 11 standard is widely used, std::auto_ptr can be used in scenarios where ownership needs to be transferred. However, it is recommended that std::auto_ptr be encapsulated. The copy constructor and assignment operator of the encapsulation class should not be used in a standard container.
2217
2218
2219### <a name="a9-5-2"></a>Recommendation 9.5.2 Use the new standard header files.
2220
2221Note:
2222When using the standard header file of C++, use `<cstdlib>` instead of `<stdlib.h>`.
2223
2224## <a name="c9-6"></a> Usage of const
2225Add the keyword const before the declared variable or parameter (example: `const int foo`) to prevent the variable from being tampered with. Add the const qualifier to the function in the class (example: `class Foo {int Bar (char c) const;} ;`) to make sure the function does not modify the status of the class member variable. const variables, data members, functions, and parameters ensure that the type detection during compilation is accurate and errors are found as soon as possible. Therefore, we strongly recommend that const be used in any possible case.
2226Sometimes it is better to use constexpr from C++ 11 to define real constants.
2227
2228### <a name="r9-6-1"></a>Rule 9.6.1 For formal parameters of pointer and reference types, if the parameters do not need to be modified, use const.
2229Unchanging values are easier to understand, trace, and analyze. `const` is used as the default option and is checked during compilation to make the code more secure and reliable.
2230```cpp
2231class Foo;
2232
2233void PrintFoo(const Foo& foo);
2234```
2235
2236### <a name="r9-6-2"></a>Rule 9.6.2 For member functions that do not modify member variables, use const.
2237Declare the member function as `const` whenever possible. The access function should always be const. So long as the function of a member is not modified, the function is declared with const.
2238When you need to modify data members in a virtual function, take all classes in the inheritance chain into account instead of only focusing on the implementation of a single class.
2239```cpp
2240class Foo {
2241public:
2242
2243    // ...
2244
2245    int PrintValue() const // const modifies member functions and does not modify member variables.
2246    {
2247        std::cout << value_ << std::endl;
2248    }
2249
2250    int GetValue() const  // const modifies member functions and does not modify member variables.
2251    {
2252        return value_;
2253    }
2254
2255private:
2256    int value_;
2257};
2258```
2259
2260### <a name="a9-6-1"></a>Recommendation 9.6.1 Member variables that will not be modified after initialization should be defined as constants.
2261
2262```cpp
2263class Foo {
2264public:
2265    Foo(int length) : dataLength_(length) {}
2266private:
2267    const int dataLength_;
2268};
2269```
2270
2271## <a name="c9.7"></a> Exceptions
2272
2273### <a name="a9-7-1"></a>Recommendation 9.7.1 If the function does not throw an exception, the declaration is `noexcept`.
2274**Reasons:**
22751. If the function does not throw an exception, the declaration is `noexcept`, which enables the compiler to optimize the function to the maximum extent, for example, reducing the execution paths and improving the efficiency of exiting when an error occurs.
22762. For STL containers such as  `vector`, to ensure the interface robustness, if the `move `  constructor of saved items is not declared as `noexcept`,  the `copy machanism` instead of the  `move machanism`  is used when the items are removed from the container. This would cause performance loss risks. If the function does not throw an exception, or a program does not intercept and process an exception thrown by the function, new `noexcept` keywords can be used to modify the function, indicating that the function does not throw an exception or the thrown exception is not intercepted or processed. For example:
2277
2278```cpp
2279extern "C" double sqrt(double) noexcept;  // No exceptions are thrown.
2280
2281// noexcept can still be used when exceptions may be thrown.
2282// The exception of memory exhaustion is not processed. The function is simply declared as noexcept.
2283std::vector<int> MyComputation(const std::vector<int>& v) noexcept
2284{
2285    std::vector res = v;    // Exceptions may be thrown.
2286    // do something
2287    return res;
2288}
2289```
2290
2291**Example:**
2292
2293```cpp
2294RetType Function(Type params) noexcept;   // Maximized optimization
2295RetType Function(Type params) noexcept;   // No optimization
2296
2297// Declaration as noexcept for the move operation of std::vector is needed.
2298class Foo1 {
2299public:
2300    Foo1(Foo1&& other);  // no noexcept
2301};
2302
2303std::vector<Foo1> a1;
2304a1.push_back(Foo1());
2305a1.push_back(Foo1()); // The copy constructor is called to enable the container expansion and removal of existing items.
2306
2307class Foo2 {
2308public:
2309    Foo2(Foo2&& other) noexcept;
2310};
2311
2312std::vector<Foo2> a2;
2313a2.push_back(Foo2());
2314a2.push_back(Foo2()); //Triggers container expansion and invokes the move constructor to move existing elements.
2315```
2316
2317**Note**
2318The default constructor, destructor, `swap` function, and `move` operator should not throw an exception.
2319
2320## <a name="c9-8"></a> Templates
2321
2322Template programming allows for extremely flexible interfaces that are type safe and high performance, enabling reuse of code of different types but with the same behavior.
2323
2324The disadvantages of template proramming are as follows:
2325
23261. The techniques used in template programming are often obscure to anyone but language experts. Code that uses templates in complicated ways is often unreadable, and is hard to debug or maintain.
23272. Template programming often leads to extremely poor compiler time error messages: even if an interface is simple, complicated implementation details become visible when the user does something wrong.
23283. If the template is not properly used, the code will be over expanded during runtime.
23294. It is difficult to modify or refactor template code. The template code is expanded in multiple contexts, and it is hard to verify that the transformation makes sense in all of them.
2330
2331Therefore, it is recommended that __ template programming be used only in a small number of basic components and basic data structure__. When using the template programming, minimize the __ complexity as much as possible, and __ avoid exposing the template__. It is better to hide programming as an implementation detail whenever possible, so that user-facing headers are readable. And you should write sufficiently detailed comments for code that uses templates.
2332
2333
2334## <a name="c9-9"></a> Macros
2335In the C++ language, it is strongly recommended that complex macros be used as little as possible.
2336- For constant definitions, use `const` or `enum` as stated in the preceding sections.
2337- For macro functions, try to be as simple as possible, comply with the following principles, and use inline functions and template functions for replacement.
2338
2339```cpp
2340// The macro function is not recommended.
2341#define SQUARE(a, b) ((a) * (b))
2342
2343// Use the template function and inline function as a replacement.
2344template<typename T> T Square(T a, T b) { return a * b; }
2345```
2346
2347For details about how to use macros, see the related chapters about the C language specifications.
2348**Exception**: For some common and mature applications, for example, encapsulation for new and delete, the use of macros can be retained.
2349
2350# <a name="c10"></a> 10 Modern C++ Features
2351
2352As the ISO released the C++ 11 language standard in 2011 and released the C++ 17 in March 2017, the modern C++ (C++ 11/14/17) adds a large number of new language features and standard libraries that improve programming efficiency and code quality.
2353This chapter describes some guidelines for modern C++ use, to avoid language pitfalls.
2354
2355## <a name="c10-1"></a> Code Simplicity and Security Improvement
2356### <a name="a10-1-1"></a>Recommendation 10.1.1 Use `auto` properly.
2357**Reasons**
2358
2359* `auto` can help you avoid writing verbose, repeated type names, and can also ensure initialization when variables are defined.
2360* The `auto` type deduction rules are complex and need to be read carefully.
2361* If using `auto` makes the code clearer, use a specific type of it and use it only for local variables.
2362
2363**Example**
2364
2365```cpp
2366// Avoid verbose type names.
2367std::map<string, int>::iterator iter = m.find(val);
2368auto iter = m.find(val);
2369
2370// Avoid duplicate type names.
2371class Foo {...};
2372Foo* p = new Foo;
2373auto p = new Foo;
2374
2375// Ensure that the initialization is successful.
2376int x;    // The compilation is correct but the variable is not initialized.
2377auto x;   // The compilation failed. Initialization is needed.
2378```
2379
2380`auto` type deduction may cause the following problems:
2381
2382```cpp
2383auto a = 3;           // int
2384const auto ca = a;    // const int
2385const auto& ra = a;   // const int&
2386auto aa = ca;         // int, const and reference are neglected.
2387auto ila1 = { 10 };   // std::initializer_list<int>
2388auto ila2{ 10 };      // std::initializer_list<int>
2389
2390auto&& ura1 = x;      // int&
2391auto&& ura2 = ca;     // const int&
2392auto&& ura3 = 10;     // int&&
2393
2394const int b[10];
2395auto arr1 = b;        // const int*
2396auto& arr2 = b;       // const int(&)[10]
2397```
2398
2399If you do not pay attention to `auto` type deduction and ignore the reference, hard-to-find performance problems may be created.
2400
2401```cpp
2402std::vector<std::string> v;
2403auto s1 = v[0]; // auto deduction changes s1 to std::string in order to copy v[0].
2404```
2405
2406If `auto` is used to define an interface, such as a constant in a header file, the type may be changed if the developer has modified the value.
2407
2408### <a name="r10-1-1"></a>Rule 10.1.1 Use the keyword `override` when rewriting virtual functions.
2409**Reason:**
2410The keyword `override` ensures that the function is a virtual function and an overridden virtual function of the base class. If the subclass function is different from the base class function prototype, a compilation alarm is generated. `final` also ensures that virtual functions are not overridden by subclasses.
2411
2412If you modify the prototype of a base class virtual function but forget to modify the virtual function overridden by the subclass, you can find inconsistency during compilation. You can also avoid forgetting to modify the overridden function when there are multiple subclasses.
2413
2414**Example**
2415
2416```cpp
2417class Base {
2418public:
2419    virtual void Foo();
2420    virtual void Foo(int var);
2421    void Bar();
2422};
2423
2424class Derived : public Base {
2425public:
2426    void Foo() const override; // Compilation failed: derived::Foo is different from that of the prototype of base::Foo and is not overridden.
2427    void Foo() override;       // Compilation successful: derived::Foo overrode base::Foo.
2428    void Foo(int var) final;   // Compilation successful: Derived::Foo(int) rewrites Base::Foo(int), and the derived class of Derived cannot override this function.
2429    void Bar() override;       // Compilation failed: base::Bar is not a virtual function.
2430};
2431```
2432
2433**Summary**
24341. When defining the virtual function for the first time based on the base class, use the keyword `virtual`.
24352. When overriding the virtual function by a subclass in a base class, including destructors, use the keyword `override` or  `final` instead of `virtual`.
24363. For the non-virtual function, do not use `virtual` or `override`.
2437
2438### <a name="r10-1-2"></a>Rule: 10.1.2 Use the keyword `delete` to delete functions.
2439**Reason**
2440The `delete` keyword is clearer and the application scope is wider than a class member function that is declared as private and not implemented.
2441
2442**Example:**
2443
2444```cpp
2445class Foo {
2446private:
2447    // Whether the copy structure is deleted or not is unknown because usually only the header file is checked.
2448    Foo(const Foo&);
2449};
2450
2451class Foo {
2452public:
2453    // Explicitly delete the copy assignment operator.
2454    Foo& operator=(const Foo&) = delete;
2455};
2456```
2457
2458The `delete` keyword can also be used to delete non-member functions.
2459
2460```cpp
2461template<typename T>
2462void Process(T value);
2463
2464template<>
2465void Process<void>(void) = delete;
2466```
2467
2468### <a name="r10-1-3"></a>Rule 10.1.3 Use `nullptr` instead of `NULL` or `0`.
2469**Reason:**
2470For a long time, C++ has not had a keyword that represents a null pointer, which is embarrassing:
2471
2472```cpp
2473#define NULL ((void *)0)
2474
2475char* str = NULL;   // Error: void* cannot be automatically converted to char*.
2476
2477void(C::*pmf)() = &C::Func;
2478if (pmf == NULL) {} // Error: void* cannot be automatically converted to the pointer that points to the member function.
2479```
2480
2481If `NULL` is defined as `0` or `0L`, the above problems can be solved.
2482
2483Alternatively, use `0` directly in places where null pointers are required. However, another problem occurs. The code is not clear, especially when `auto` is used for automatic deduction.
2484
2485```cpp
2486auto result = Find(id);
2487if (result == 0) {  // Does Find() return a pointer or an integer?
2488    // do something
2489}
2490```
2491
2492Literally `0` is of the `int` type (`0L` is the `long` type). Therefore, neither `NULL` nor `0` is a pointer type.
2493When a function of the pointer or integer type is overloaded, `NULL` or `0` calls only the overloaded pointer function.
2494
2495```cpp
2496void F(int);
2497void F(int*);
2498
2499F(0);      // Call F(int) instead of F(int*).
2500F(NULL);   // Call F(int) instead of F(int*).
2501```
2502
2503In addition, `sizeof(NULL) == sizeof(void*)` does not always make sense, which is a potential risk.
2504
2505Summary: If `0` or `0L` is directly used, the code is not clear and type security cannot be ensured. If `NULL` is used, the type security cannot be ensured. These are all potential risks.
2506
2507`nullptr` has many advantages. It literally represents the null pointer and makes the code clearer. More to the point, it is no longer an integer type.
2508
2509`nullptr` is of the `std::nullptr_t` type. `std::nullptr_t` can be implicitly converted into all original pointer types, so that `nullptr` can represent a null pointer that points to any type.
2510
2511```cpp
2512void F(int);
2513void F(int*);
2514F(nullptr);   // Call F(int*).
2515
2516auto result = Find(id);
2517if (result == nullptr) {  // Find() returns a pointer.
2518    // do something
2519}
2520```
2521
2522### <a name="r10-1-4"></a>Rule 10.1.4 Use `using` instead of `typedef`.
2523For versions earlier than `C++11`, you can define the alias of the type by using `typedef`. No one wants to repeat code like `std::map<uint32_t, std::vector<int>>`.
2524
2525```cpp
2526typedef std::map<uint32_t, std::vector<int>> SomeType;
2527```
2528
2529Using alias for the type is actually encapsulating the type. This encapsulation makes the code clearer, and to a large extent avoids the bulk modification caused by the type change.
2530For versions supporting C++ 11 features, `using` is provided to implement `alias declarations`:
2531
2532```cpp
2533using SomeType = std::map<uint32_t, std::vector<int>>;
2534```
2535
2536Compare the two formats:
2537
2538```cpp
2539typedef Type Alias;   // It cannot be told whether the original Type or Alias is at the front.
2540using Alias = Type;   // The format confirms to the assignment rule. It is easy to understand and helps reduce errors.
2541```
2542
2543If this is not enough to prove the advantages of `using`, the alias template may be a better example:
2544
2545```cpp
2546//: Only one line of code is need to define an alias for a template.
2547template<class T>
2548using MyAllocatorVector = std::vector<T, MyAllocator<T>>;
2549
2550MyAllocatorVector data;       // An alias for a template defined with "using".
2551
2552template<class T>
2553class MyClass {
2554private:
2555    MyAllocatorVector data_;   // Another.
2556};
2557```
2558
2559`typedef` does not support alias templates and they have to be hacked in.
2560
2561```cpp
2562// A template is used for packaging typedef. Therefore, a template class is needed.
2563template<class T>
2564struct MyAllocatorVector {
2565    typedef std::vector<T, MyAllocator<T>> type;
2566};
2567
2568MyAllocatorVector::type data;  // ::type needs to be added when using typedef to define an alias.
2569
2570template<class T>
2571class MyClass {
2572private:
2573    typename MyAllocatorVector::type data_;  // For a template class, typename is also needed in addition to ::type.
2574};
2575```
2576
2577### <a name="r10-1-5"></a>Rule 10.1.5 Do not use std::move to operate the const object.
2578Literally, `std::move` means moving an object. The const object cannot be modified and cannot be moved. Therefore, using `std::move` to operate the const object may confuse code readers.
2579Regarding actual functions, `std::move` converts an object to the rvalue reference type. It can convert the const object to the rvalue reference of const. Because few types define the move constructor and the move assignment operator that use the const rvalue reference as the parameter, the actual function of code is often degraded to object copy instead of object movement, which brings performance loss.
2580
2581**Bad example:**
2582```cpp
2583std::string g_string;
2584std::vector<std::string> g_stringList;
2585
2586void func()
2587{
2588    const std::string myString = "String content";
2589    g_string = std::move(myString); // Bad: myString is not moved. Instead, it is copied.
2590    const std::string anotherString = "Another string content";
2591    g_stringList.push_back(std::move(anotherString));    // Bad: anotherString is not moved. Instead, it is copied.
2592}
2593```
2594
2595## <a name="c10-2"></a> Smart Pointers
2596### <a name="r10-2-1"></a>Rule 10.2.1 Use smart pointers instead of a raw pointer to manage resources.
2597**Reason:**
2598Avoid resource leakage.
2599
2600**Example:**
2601
2602```cpp
2603void Use(int i)
2604{
2605    auto p = new int {7};               // Bad: Initializing local pointers with new.
2606    auto q = std::make_unique(9);  // Good: Guarantee that memory is released.
2607    if (i > 0) {
2608        return;                           // Return and possible leak.
2609    }
2610    delete p;                           // Too late to salvage.
2611}
2612```
2613
2614**Exception:**
2615Raw pointers can be used in scenarios requiring high performance and compatibility.
2616
2617### <a name="r10-2-2"></a>Rule 10.2.2 Use `unique_ptr` instead of `shared_ptr`.
2618**Reasons:**
26191. Using `shared_ptr` a lot has an overhead (atomic operations on the `shared_ptr`s reference count have a measurable cost).
26202. Shared ownership in some cases (such as circular dependency) may create objects that can never be released.
26213. Shared ownership can be an attractive alternative to careful ownership design but it may obfuscate the design of a system.
2622
2623### <a name="r10-2-3"></a>Rule 10.2.3 Use `std::make_unique` instead of `new` to create a `unique_ptr`.
2624**Reasons:**
26251. `make_unique` provides a simpler creation method.
26262. `make_unique` ensures the exception safety of complex expressions.
2627
2628**Example:**
2629
2630```cpp
2631// Bad: MyClass appears twice, which carries a risk of inconsistency.
2632std::unique_ptr<MyClass> ptr(new MyClass(0, 1));
2633// Good: MyClass appears once and there is no possibility of inconsistency.
2634auto ptr = std::make_unique<MyClass>(0, 1);
2635```
2636
2637Recurrence of types may cause serious problems, and it is difficult to find them:
2638
2639```cpp
2640// The code compiles fine, but new and delete usage does not match.
2641std::unique_ptr<uint8_t> ptr(new uint8_t[10]);
2642std::unique_ptr<uint8_t[]> ptr(new uint8_t);
2643// No exception safety: The compiler may calculate parameters in the following order:
2644// 1. Allocate the memory of Foo.
2645// 2. Construct Foo.
2646// 3. Call Bar.
2647// 4. Construct unique_ptr<Foo>.
2648// If Bar throws an exception, Foo is not destroyed and a memory leak occurs.
2649F(unique_ptr<Foo>(new Foo()), Bar());
2650
2651// Exception safety: Calling of function is not interrupted.
2652F(make_unique<Foo>(), Bar());
2653```
2654
2655**Exception:**
2656`std::make_unique` does not support user-defined `deleter`.
2657In the scenario where the `deleter` needs to be customized, it is recommended that `make_unique` be implemented in the customized version’s own namespace.
2658Using `new` to create `unique_ptr` with the user-defined `deleter` is the last choice.
2659
2660### <a name="r10-2-4"></a>Rule 10.2.4 Create `shared_ptr` by using `std::make_shared` instead of `new`.
2661**Reason:**
2662In addition to the consistency factor similar to that in `std::make_unique` when using `std::make_shared`, performance is also a factor to consider.
2663`std::shared_ptr` manages two entities:
2664* Control block (storing reference count, `deleter`, etc.)
2665* Managed objects
2666
2667When `std::make_shared` creates `std::shared_ptr`, it allocates sufficient memory for storing control blocks and managed objects on the heap at a time. When `std::shared_ptr<MyClass>(new MyClass)`is used to create a `std::shared_ptr`, not only does `new MyClass` trigger heap allocation, but the constructor function of `std::shard_ptr` triggers a second heap allocation, resulting in extra overhead.
2668
2669**Exception:**
2670Similar to `std::make_unique`, `std::make_shared` does not support `deleter` customization.
2671
2672## <a name="c10-3"></a> Lambda
2673### <a name="a10-3-1"></a>Recommendation 10.3.1 Use `lambda` to capture local variables or write local functions when normal functions do not work.
2674**Reason:**
2675Functions cannot capture local variables or be declared at local scope. If you need those things, choose `lambda` instead of handwritten `functor`.
2676On the other hand, `lambda` and `functor` objects do not support overloading. If overloading is required, use a function.
2677If both `lambda` and functions work, a function is preferred. Use the simplest tool.
2678
2679**Example:**
2680
2681```cpp
2682// Write a function that accepts only an int or string.
2683// -- Overloading is more natural.
2684void F(int);
2685void F(const string&);
2686
2687// The local state needs to be captured or appear in the statement or expression range.
2688// -- A lambda is more natural.
2689vector<Work> v = LotsOfWork();
2690for (int taskNum = 0; taskNum < max; ++taskNum) {
2691    pool.Run([=, &v] {...});
2692}
2693pool.Join();
2694```
2695
2696### <a name="r10-3-1"></a>Rule 10.3.1 Avoid capturing by reference in lambdas that will not be used locally.
2697**Reason:**
2698Using `lambdas` at a "nonlocal" scope includes returning, storing on the heap, and passing to another thread. Local pointers and references should not outlive their scope. Capturing by reference in `lambdas` indicates storing a reference to a local object. If this leads to a reference that exceeds the lifecycle of a local variable, capturing by reference should not be used.
2699
2700**Example:**
2701
2702```cpp
2703// Bad
2704void Foo()
2705{
2706    int local = 42;
2707    // Capture a reference to a local variable.
2708    // After the function returns results, local no longer exists,
2709    // Process() call will have undefined behavior.
2710    threadPool.QueueWork([&]{ Process(local); });
2711}
2712
2713// Good
2714void Foo()
2715{
2716    int local = 42;
2717    // Capture a copy of local.
2718    // Since a copy of local is made, it will be always available for the call.
2719    threadPool.QueueWork([=]{ Process(local); });
2720}
2721```
2722
2723### <a name="a10-3-2"></a>Recommendation 10.3.2 All variables are explicitly captured if `this` is captured.
2724**Reason:**
2725The `[=]` in the member function seems to indicate capturing by value but actually it is capturing data members by reference because it captures the invisible `this` pointer by value. Generally, it is recommended that capturing by reference be avoided. If it is necessary to do so, write `this` explicitly.
2726
2727**Example:**
2728
2729```cpp
2730class MyClass {
2731public:
2732    void Foo()
2733    {
2734        int i = 0;
2735
2736        auto Lambda = [=]() { Use(i, data_); };   // Bad: It looks like we are copying or capturing by value but member variables are actually captured by reference.
2737
2738        data_ = 42;
2739        Lambda(); // Call use(42);
2740        data_ = 43;
2741        Lambda(); // Call use(43);
2742
2743        auto Lambda2 = [i, this]() { Use(i, data_); }; // Good: the most explicit and least confusing method.
2744    }
2745
2746private:
2747    int data_ = 0;
2748};
2749```
2750
2751### <a name="a10-3-3"></a>Recommendation 10.3.3 Avoid default capture modes.
2752**Reason:**
2753The lambda expression provides two default capture modes: by-reference (&) and by-value (=).
2754By default, the "by-reference" capture mode will implicitly capture the reference of all local variables, which will easily lead to dangling references. By contrast, explicitly writing variables that need to be captured can make it easier to check the lifecycle of an object and reduce the possibility of making a mistake.
2755By default, the "by-value” capture mode will implicitly capture this pointer, and it is difficult to find out which variables the lambda function depends on. If a static variable exists, the reader mistakenly considers that the lambda has copied a static variable.
2756Therefore, it is required to clearly state the variables that lambda needs to capture, instead of using the default capture mode.
2757
2758**Bad example:**
2759```cpp
2760auto func()
2761{
2762    int addend = 5;
2763    static int baseValue = 3;
2764
2765    return [=]() {  // Only addend is actually copied.
2766        ++baseValue;    // The modification will affect the value of the static variable.
2767        return baseValue + addend;
2768    };
2769}
2770```
2771
2772**Good example:**
2773```cpp
2774auto func()
2775{
2776    int addend = 5;
2777    static int baseValue = 3;
2778
2779    return [addend, baseValue = baseValue]() mutable {  // Uses the C++14 capture initialization to copy a variable.
2780        ++baseValue;    // Modifying the copy of a static variable does not affect the value of the static variable.
2781        return baseValue + addend;
2782    };
2783}
2784```
2785
2786Reference: Effective Modern C++: Item 31: Avoid default capture modes.
2787
2788## <a name="c10-4"></a> Interfaces
2789### <a name="a10-4-1"></a>Recommendation 10.4.1 Use `T*` or `T&` arguments instead of a smart pointer in scenarios where ownership is not involved.
2790**Reasons:**
27911. Passing a smart pointer to transfer or share ownership should only be used when the ownership mechanism is explicitly required.
27922. Passing a smart pointer (for example, passing the `this` smart pointer) restricts the use of a function to callers using smart pointers.
27933. Passing a shared smart pointer adds a runtime performance cost.
2794
2795**Example:**
2796
2797```cpp
2798// Accept any int*.
2799void F(int*);
2800
2801// Accept only integers for which you want to transfer ownership.
2802void G(unique_ptr<int>);
2803
2804// Accept only integers for which you want to share ownership.
2805void G(shared_ptr<int>);
2806
2807// Does not need to change the ownership but requires ownership of the caller.
2808void H(const unique_ptr<int>&);
2809
2810// Accept any int.
2811void H(int&);
2812
2813// Bad
2814void F(shared_ptr<Widget>& w)
2815{
2816    // ...
2817    Use(*w); // When only w is used, lifecycle management is not required.
2818    // ...
2819};
2820```
2821
2822