High quality c ++ Programming Guide (C ++ programming specifications)

Source: Internet
Author: User

It is very useful to read this book, but some common rules are not listed one by one. Just write down the rules that were not so clear before.

Code Quality Assurance priority principle:
(1) Correctness refers to the function that the program needs to implement the design requirements.
(2) stability and security means that the program is stable, reliable, and secure.
(3) testability means that the program should have good testability.
(4) specification/Readability: The program Writing Style and naming rules must comply with the specifications.
(5) global efficiency refers to the overall efficiency of the software system.
(6) Local Efficiency refers to the efficiency of a module, submodule, or function.
(7) personal expressions/personal convenience refer to personal programming habits.

In C, static local variables are generated in the memory "Data zone", rather than static local variables are generated in the "stack.
Long statement into multiple lines write ratio: in the lower-priority operator division of the new line, each row can have a relatively independent and complete meaning, thus more clear. When the line is broken, the operator must release the first line. The new lines to be split should be properly indented to make the layout neat and the statement readable.
If a new variable needs to be defined in the case statement, it must be included in {}; otherwise, {} is not required {}.
After the memory is released, you must set the pointer to null.
When programming, avoid 1 error.
If possible, add the else branch to the IF statement as much as possible, and be careful with the statements without the else branch; the switch statement must have the default branch.
Resource file (multi-language version supported). If the resource is language sensitive, the resource should be separated from the source code file. The specific methods are as follows: use a separate resource file, DLL file, or other separate description file (such as database format)
Some statements are compiled to generate alerts, But if you confirm that they are correct, you should remove the alert information by some means.

In C ++, function parameters and return values are transmitted in three ways: value transfer, pointer transfer, and reference transfer.
Memory Allocation:
There are three memory allocation methods:
(1) distribution from the static storage area. The program has been allocated when it is compiled, and the program exists throughout the entire runtime. For example, global variables and static variables.
(2) create a stack. When a function is executed, the storage units of local variables in the function can be created on the stack. When the function is executed, these storage units are automatically released. Stack memory allocation computation is built into the processor's instruction set, which is highly efficient, but the memory capacity allocated is limited.
(3) allocate from the stack, also known as dynamic memory allocation. When the program runs, it uses malloc or new to apply for any amount of memory. The programmer is responsible for releasing the memory with free or delete. The lifetime of the dynamic memory is determined by us. It is very flexible to use, but the problem is that the memory is released at most, but it continues to be used.
There are three scenarios:
(1) The object calling relationship in the program is too complex, so it is difficult to figure out whether an object has released the memory. At this time, we should re-design the data structure to fundamentally solve the chaos of Object Management.
(2) The Return Statement of the function is incorrect. Be sure not to return the "Pointer" or "Reference" pointing to "stack memory" because the function body is automatically destroyed when it ends.
(3) After the memory is released using free or delete, the pointer is not set to null. As a result, a "wild pointer" is generated ".
Char A [] = "hello ";
A [0] = 'X ';
Cout <A <Endl;
Char * P = "world"; // note that P points to a constant string
P [0] = 'X'; // the compiler cannot find this error.
Cout <p <Endl;
Format:
Empty rows must be added after each class declaration and after each function definition.
Add space:
Do not leave a space after the function name, followed by the left brace '(', to be different from the keyword.
'('Backward followed,') ','; 'follow forward without spaces.
For example, if, for, while, and other keywords, leave a space with the left brace '(' to highlight the keyword.
If ';' is not the end symbol of a row, leave a space after it, such as for (initialization; condition; update ).
If, for, while, switch, and so on should be added with a space between the brackets to make if and other keywords more prominent and obvious.
Commas (,) and semicolons (;) are only followed by spaces.
Value assignment operator, comparison operator, arithmetic operator, logical operator, bitfield operator, such as "=", "+ =" "> =", "<=", "+", "*", "%", "&", and "|", "<", "^" and other binary operators should be preceded by spaces.
The unary operator is like "!". , "~" , "+ +", "--", "&" (Address operator) and so on without spaces.
The modifier * and & should be placed close to the variable name
If the modifier * is close to the data type, for example, int * X, it is more intuitive in semantics, that is, X is
Int type pointer.
The disadvantage of the above writing is that it is easy to misunderstand, for example, int * X, Y; here y is easy to be misunderstood as a pointer variable.
Although defining branch X and branch y can avoid misunderstanding, not everyone is willing to do so.
For long for statements and if statements, some spaces can be removed for compact purposes, such as for (I = 0; I <10; I ++) and if (A <= B) & (c <= D ))
Bad practice: for (I = 0; I <10; I ++) // too many spaces
Note:
You must write comments on the definition of variables and the branch statements (such as condition branches and loop statements.
Good practice: When the code size is large and the logic is complex, it is helpful to clarify the ideas by writing comments and then writing code.
Separate the comments from the code above with blank lines.
In a well-named program, you can reduce comments and make full use of the self-Comments of the Code.
The purpose of comments is to explain the purpose, functions, and methods of the Code, provide information other than the code, help readers understand the code, and prevent unnecessary repeated comments.
By correctly naming functions, processes, variables, structures, and so on, and reasonably organizing the code structure, the Code becomes self-Annotated.
Parameters:
Specify whether the caller of the function is responsible for checking the validity of interface function parameters or the interface function itself. By default, the caller is responsible.
Non-scheduling functions should reduce or prevent control parameters and use only data parameters as much as possible. (This suggestion aims to prevent control coupling between functions. A scheduling function starts a function entity (a function or process) based on the input message type or control command, but does not complete a specific function. A control parameter is a parameter used to change the function behavior. That is, a function depends on this parameter to determine how it works. The control parameters of non-scheduled functions increase the control coupling between functions, which may increase the Coupling Degree between functions and make functions ununique .)
Function:
Small functions are not clearly defined, especially when only one upper-level function calls it, you should consider merging it into the upper-level function without having to exist independently.
When a process (function) has many references to long variables (usually structure members), a macro can be used instead.
Example: If thereceivebuffer [firstsocket]. bydataptr is referenced in a process, the following macro definition can be used instead: # define psockdata thereceivebuffer [firstscoket]. bydataptr
Debug:
The format of the information string printed during commissioning and testing of the same project must be in a unified manner. The information string must contain at least the module name (or source file name) and the row number.
Use assertions to discover software problems and improve code testability.
The following is an asserted in C language, designed with a macro. (Null is 0l)
# Ifdef _ exam_assert_test _ // If asserted test is used

Void exam_assert (char * file_name, unsigned int line_no)
{
Printf ("\ n [exam] assert failed: % s, line % u \ n ",
File_name, line_no );
Abort ();
}

# Define exam_assert (condition)
If (condition) // if the condition is true, no action is performed.
NULL;
Else // otherwise report
Exam_assert (_ file __, _ line __)

# Else // if no asserted test is used

# Define exam_assert (condition) null

# Endif/* end of assert */
Loop:
In multiple cycles, the busiest cycle should be placed in the innermost layer. (Note: Reduce the number of times the CPU is switched into the cycle layer .)
In multiple cycles, if possible, the longest cycle should be placed in the innermost layer, and the shortest cycle should be placed in the outermost layer to reduce the number of times the CPU switches across the cycle layer.
To avoid the inclusion of judgment statements in the loop body, the circular statements should be placed in the code block of the judgment statement. (Note: The purpose is to reduce the number of judgments. The judgment statement in the cyclic body can be moved to the circulating body. Generally, the judgment statement irrelevant to the cyclic variable can be moved to the circulating body according to the specific circumstances of the program, but not related .)
Details:
Try to use multiplication or other methods instead of division, especially in floating point operations. (Description: The Floating Point Operation Division takes up a large amount of CPU resources. # Define pai_reciprocal (1/3.1416) // a specific floating point number will be generated during compiler compilation)

////////////////////////////////

Header file:
Header file function:
(1) Use the header file to call the library function. In many cases, the source code is inconvenient (or inaccurate) to publish to users, as long as the header file and binary library are provided to users. You only need to follow the interface declaration in the header file to call the library function, without worrying about how the interface is implemented. The compiler extracts the corresponding code from the library.
(2) the header file can enhance the type security check. If an interface is implemented or used in a different way than the declaration in the header file, the compiler will point out an error. This simple rule can greatly reduce the burden on programmers to debug and correct errors.
The header file only stores "Declaration" instead of "Definition". The header file must contain definitions.
We do not recommend using global variables. do not include declarations such as extern int value in header files. ; Extern function (refer to C ++ programming)
Class:
(1) write private-type data in front and public-type functions in the back. Programmers who use this layout claim the design of the class "data-centric", focusing on the internal structure of the category.
(2) Write Functions of the Public type in front and data of the private type in the back. The programmer who uses this layout claims that the design of the class is "behavior-centric", focusing on the interface (or service) that the class should provide ).
The same name of a global function and a class member function is not considered a heavy load because the function has different scopes.

The ':' flag should be added when the global function is called. For example: Print (...); // Indicates that print is a global function rather than a member function.
Features of member functions being overloaded:
(1) the same range (in the same class );
(2) The function name is the same;
(3) parameters are different;
(4) virtual keywords are optional.
Override refers to the function of a derived class that overwrites the base class function. The features are as follows:
(1) different scopes (located in the derived class and the base class respectively );
(2) The function name is the same;
(3) The parameters are the same;
(4) basic functions must have virtual keywords.
"Hide" means that the function of the derived class shields the base class functions with the same name. The rules are as follows:
(1) If the function of the derived class has the same name as the function of the base class, but the parameter is different. In this case, functions of the base class will be hidden regardless of whether there is any virtual keyword (Be sure not to confuse them with overload ).
(2) If the function of the derived class has the same name and parameter as the function of the base class, but the base class function does not have the virtual keyword. In this case, the function of the base class is hidden (do not confuse with overwrite ).
Many C ++ programmers do not realize the "hiding" issue. Due to lack of deep understanding, the occurrence of "hiding" is a real failure and often produces confusing results.
Initialization expression table (initialization table): the initialization table is located after the function parameter table, but before the function body. This indicates that the initialization work in the table occurs before any code in the function body is executed.

Rules for using constructors to initialize tables:
If the class has an inheritance relationship, the derived class must call the base class constructor in its initialization table.
The const constant of the class can only be initialized in the initialization table, because it cannot be initialized in the function body by assigning values.
Non-Internal data type member objects should be initialized in the first way to achieve higher efficiency.

If you do not write the copy constructor and value assignment function, the compiler automatically generates the default function in the "bit copy" mode. If the class contains pointer variables, the two default functions are implicitly incorrect. The pointer variables in the objects before and after the value assignment will point to the same memory, so that the memory cannot be correctly released.
String c = A; // call the copy constructor. It is best to write it as C ();
C = B; // The Value assignment function is called.
The style of the third statement is poor. It should be rewritten to string C (A) to distinguish it from the fourth statement.

If there is an inheritance relationship between classes, pay attention to the following when writing the above basic functions:
The constructor of the derived class should call the constructor of the base class in its initialization table.
The destructor of the base class and the derived class should be virtual (that is, the virtual keyword is added)
Name:
In general, long names can better express meanings. Therefore, function names, variable names, and class names can contain up to a dozen characters. So is the name a longer appointment? No! For example, the variable name maxval is better than maxvalueuntiloverflow. Single-character names are also useful. Common ones include I, J, K, M, N, x, y, and z. They are usually used as local variables in functions.
The identifiers of Windows applications are usually mixed in upper and lower cases, such as addchild. The identifier of a Unix application is usually "lowercase and underlined", for example, add_child.
The name of a global function should be "verb" or "Verb + noun" (verb phrase ). Class member functions should only use the "verb", and the omitted nouns are the object itself.
Simple naming rules for Windows Applications
The authors have simplified the naming rules of Hungary. The following naming rules are simple and easy to use, and are suitable for the development of Windows application software.
Rule 3-2-1: The class name and function name are combined with words starting with an upper-case letter.
For example:
Class node; // Class Name
Class leafnode; // Class Name
Void draw (void); // function name
Void setvalue (INT value); // function name

Rule 3-2-2: a combination of variables and parameters starting with a lowercase letter.
For example:
Bool flag;
Int drawmode;

[Rule 3-2-3] constants are all separated by uppercase letters and underscores.
For example:
Const int max = 100;
Const int max_length = 100;

[Rule 3-2-4] Static variables are prefixed with S _ (indicating static ).
For example:
Void Init (...)
{
Static int s_initvalue; // static variable
...
}

[Rule 3-2-5] If you have to require a global variable, add the global variable with the prefix G _ (indicating global ).
For example:
Int g_howmanypeople; // global variable
Int g_howmuchmoney; // global variable

[Rule 3-2-6] data members of the class are prefixed with m_( indicating Member), which can avoid
The parameter of the member function has the same name.
For example:
Void object: setvalue (INT width, int height)
{
M_width = width;
M_height = height;
} [Rule 3-2-7] to prevent conflicts between some identifiers in a software library and other software libraries
Various identifiers are prefixed with software. For example, all library functions of 3D graphics standard OpenGL
All start with GL, and all constants (or macro definitions) start with GL
Comparison:
Boolean variables cannot be compared directly with true, false, or 1 or 0.
Do not use "=" or "! = "Compare with any number.
Integer variables should be replaced with "=" or "! = "Is directly compared with 0.
Constant:
Sometimes we want some constants to be valid only in the class. The const data member does exist, but its meaning is not what we expected. The const data member is a constant only within the lifetime of an object, but it is variable for the entire class, because the class can create multiple objects, the values of the const data members of different objects can be different. The const data member cannot be initialized in the class declaration. Const data member initialization can only be performed in the class constructor initialization table.
If the input parameter is passed as a value, you should use the "const &" method to transfer the object. This saves the construction and analysis processes of the temporary object and improves the efficiency.

The value of sizeof (a) is 12 (do not forget '\ 0 '). The pointer P points to A, but the value of sizeof (P) is 4. This is because sizeof (p) obtains the number of bytes of a pointer variable, which is equivalent to sizeof (char *) rather than the memory capacity referred to by P. C ++/C language cannot know the memory capacity referred to by the pointer unless you remember it when applying for memory. Note: When an array is passed as a function parameter, the array will automatically degrade to a pointer of the same type. In Example 7-3-3 (B), sizeof (a) is always equal to sizeof (char *) regardless of the size of array *).

When releasing an object Array Using Delete, do not lose the symbol '[]'. For example
Delete [] objects; // correct usage
Delete objects; // incorrect usage
The latter is equivalent to delete objects [0], and 99 Other objects are missing.

C ++ programs cannot directly call C functions because their compiled names are different. C ++ provides a C connection to exchange the specified symbol extern "C" to solve this problem.
For example:
Extern "C"
{
Void Foo (int x, int y );
... // Other functions
}
Or write it
Extern "C"
{
# Include "myheader. h"
... // Other C header files
}
This tells C ++ to compile the interpreter. The function foo is a C connection. You should find the name _ Foo in the library instead of _ foo_int_int. The C ++ compiler developer has processed the header files of the C standard library as extern "C", so we can use # include to directly reference these header files.

If a function has multiple parameters, the parameters can only be taken from the back to the front by default. Otherwise, the function call statement is strange. Unreasonable use of the parameter default value will lead to the ambiguity of the output function of the overload function.

Replacing macro code with Inline
Inline is a keyword used for implementation, rather than a keyword used for declaration ". Generally, you can read the declaration of a function, but cannot see the definition of a function. For any inline function, the compiler puts the declaration of the function (including the name, parameter type, and return value type) in the symbol table ). If the compiler does not find an error in the inline function, the code of the function is also placed in the symbol table. When calling an inline function, the compiler first checks whether the call is correct (for a type security check or automatic type conversion, of course, all functions are the same ). If correct, the code of the inline function replaces the function call directly, saving the overhead of the function call. This process is significantly different from preprocessing because the pre-processor cannot perform type security checks or perform automatic type conversion.
The member functions defined in the class declaration will automatically become inline functions; putting the definition body of the member functions in the class declaration can bring convenience in writing, but it is not a good programming style; put the class member functions in the declared external definition, and then add the inline keyword.
Inline is at the cost of code expansion (replication). It only saves the overhead of function calls and improves the function execution efficiency. If the execution time of code in the function body is higher than the overhead of function calling, the efficiency gains will be little. On the other hand, every call to an inline function must copy the code, which will increase the total amount of code in the program and consume more memory space. Inline is not recommended in the following cases:
(1) If the code in the function body is long, using inline will cause high memory consumption.
(2) If there is a loop in the function body, the execution time of the Code in the function body is longer than the overhead of the function call.
A good compiler will automatically cancel unworthy inline based on the definition body of the function.

The list initialization efficiency is more efficient than assigning values in the constructor.
First, let's take a look at object creation. Object creation involves two steps:
1. Data member initialization.
2. Execute the actions in the called constructor body.
When a non-basic type member variable exists in the class,
In the first step, the constructor of non-basic type members is called first. then, call the constructor of the current class. If the constructor has another value assignment operation, you need to execute another value assignment function.
If the initialization list is used, different results are returned. Non-basic type members can only directly call the parameter-containing constructor of their member types in the first step.

High increase and decrease efficiency

The post-increment or decrement operation will implicitly generate a temporary variable because it will save the value before the operation as the value of this statement. If you add or remove the base type after the operation, when you do not need to use the value before the operation, the action to generate the temporary variable will be optimized by the compiler. However, it is difficult to optimize the compiler for post operations that have been overloaded. It is especially common to use the auto-increment operation of the iterator when using the standard library. You should try to use the pre-increment or deprefix operations as much as possible.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.