Scope
1. Namespaces)
In. in the cc file, it is recommended that you use an unnamed namespaces (unnamed namespaces). Note: An untitled namespace is just like an untitled class and seems to be rarely introduced: -(). When using a namespace, its name can be based on the project or path name. Do not use the using indicator.
Definition: The namespace divides global scopes into different and named scopes, effectively preventing name conflicts in global scopes.
Advantage: namespace provides (nesting) The nameaxis (name axis). Note: naming is divided into different namespaces. Of course, classes also provide (nesting) (Translator's note: naming is divided into different classes ).
For example, the global scopes of two different projects have a class Foo, which causes conflicts during compilation or running. If each project places the code in a different namespace, project1: Foo and project2: Foo will not conflict with each other as different symbols.
Disadvantage: namespaces are confusing because they provide additional (nested) Naming axes like classes. Using an unspecified space in the header file is easy to violate the One Definition Rule (ODR) Principle of C ++ )).
Conclusion: The namespace can be reasonably used according to the policy described below.
1) Unnamed Namespaces)
In the. cc file, you can or even advocate using an anonymous namespace to avoid name conflicts during the runtime:
Namespace {// In the. cc File
// The namespace content does not need to be indented
Enum {UNUSED, EOF, ERROR}; // frequently used symbol
Bool AtEof () {return pos _ = EOF;} // use the EOF symbol in this namespace
} // Namespace
However, the file scope declaration associated with a specific class is declared as a type, static data member, or static member function in this class, rather than an anonymous namespace member. As shown above, the namespace is identified by the end of the namespace.
You cannot use an anonymous namespace in A. H file.
2) namespace (Named Namespaces)
The namespace can be used as follows:
The namespace encapsulates all the source files except file inclusion, global identity Declaration/definition, and class pre-declaration to distinguish them from other namespaces.
//. H file
Namespace mynamespace {
// All declarations are placed in the namespace
// Do not use indentation
Class MyClass {
Public:
...
Void Foo ();
};
} // Namespace mynamespace
//. Cc File
Namespace mynamespace {
// All function definitions are placed in the namespace
Void MyClass: Foo (){
...
}
} // Namespace mynamespace
Common. cc files contain more and more complex details, including references to classes in other namespaces.
# Include "a. h"
DEFINE_bool (someflag, false, "dummy flag ");
Class C; // The predeclaration of class C in the global namespace
Namespace a {class A;} // predeclaration of class a: a in namespace
Namespace B {
... Code for B... // code in B
} // Namespace B
Do not declare anything under the namespace std, including the pre-declaration of the standard library class. Declaring the entity under std will lead to ambiguous behaviors, for example, cannot be transplanted. Declare the entity under the standard library and contain the corresponding header file.
It is best not to use the using indicator to ensure that all names in the namespace can be used normally.
// Disable -- contaminated namespace
Using namespace foo;
You can use using in functions, methods, or classes of. cc files and. H files.
// Allow: In the. cc File
// The. h file must be used inside a function, method, or class.
Using: foo: bar;
In the. cc file and. h file functions, methods, or classes, you can also use namespace aliases.
// Allow: In the. cc File
// The. h file must be used inside a function, method, or class.
Namespace fbz =: foo: bar: baz;
2. Nested Class)
When exposing Nested classes as part of interfaces, although they can be directly stored in the global scope, it is better to place the declaration of Nested classes in the namespace.
Definition: You can define another class in a class. A nested class is also called a member class ).
Class Foo {
Private:
// Bar is a member class nested in Foo.
Class Bar {
...
};
};
Advantage: It is useful when nested (member) classes are used only in nested classes, placing it in the scope of the nested class as a member of the nested class will not pollute the class of the same name in other scopes. You can declare a nested class in the nested class. define Nested classes in the cc file to avoid including the definition of Nested classes in the nested classes, because the definition of Nested classes is usually only related to the implementation.
Disadvantage: The nested class can be pre-declared only in the definition of the nested class. Therefore, any header file that uses the Foo: Bar * pointer must contain the entire Foo declaration.
Conclusion: do not define Nested classes as public unless they are part of an interface. For example, a method uses a series of options for this class.
3. Non-Member Functions (Nonmember), Static Member Functions (Static Member), and Global Functions)
Use non-member or static member functions in a namespace. Do not use global functions whenever possible.
Advantage: in some cases, non-member functions and static member functions are very useful. placing non-member functions in a namespace can avoid global scope pollution.
Disadvantage: it may be more meaningful to use non-member and static member functions as members of the new class, especially when they need to access external resources or have important dependencies.
Conclusion:
Sometimes it is helpful not to limit a function to the entity of the class, or even to do so, either as a static member or as a non-member function. Non-member functions should not depend on external variables and should be placed in a namespace as much as possible. It is better to use a namespace than to create a class simply to encapsulate a number of static member functions that do not share any static data.
Functions defined in the same compilation unit may introduce unnecessary coupling and connection dependencies when called directly by other compilation units. static member functions are especially sensitive to this. You can consider extracting the function to a new class or placing the function in the namespace of an independent library.
If you need to define a non-member function. cc file. You can use an unnamed namespace or static Association (such as static int Foo (){...}) limits its scope.
4. Local Variables)
Place function variables in the smallest possible scope and initialize them when declaring variables.
C ++ allows variables to be declared anywhere in the function. We advocate declaring variables in the smallest possible scope. The closer we are to the first use, the better. This makes the code easy to read and easily locates the declared position, type, and initial value of the variable. In particular, initialization should be used instead of Declaration + assignment.
Int I;
I = f (); // bad -- initialization and declaration Separation
Nt j = g (); // Well -- declared during initialization
Note: gcc can correctly execute for (int I = 0; I <10; ++ I) (the scope of I is only for the for loop), so I can be reused in other for loops. Scope declaration is also correct in if and while statements.
While (const char * p = strchr (str,/) str = p + 1;
Note: If a variable is an object, its constructor must be called every time it enters the scope, and its destructor must be called every time it exits the scope.
// Inefficient implementation
For (int I = 0; I <1000000; ++ I ){
Foo f; // The constructor and destructor call 1000000 times respectively!
F. DoSomething (I );
}
It is much more efficient to put variables out of the circular scope:
Foo f; // The constructor and destructor are called only once.
For (int I = 0; I <1000000; ++ I ){
F. DoSomething (I );
}
5. Global Variables)
Global variables of the class type are forbidden, and built-in global variables are allowed. Of course, non-constant global variables in multi-threaded Code are also forbidden. Never use function return values to initialize global variables.
Unfortunately, the calling sequence of the constructor, destructor, and initialization operations of global variables is only partially specified. Each generation may change, resulting in hard-to-find buckets.
Therefore, global variables of the class type (including STL string, vector, and so on) are prohibited, because their initialization sequence may cause structural problems. Built-in types and struct composed of built-in types without constructors can be used. If you must use global variables of the class type, use singleton pattern ).
For global string constants, use a C-style string instead of an STL string:
Const char kFrogSays [] = "ribbet ";
Although global variables can be used in the global scope, you must think twice. Most global variables should be static data members of the class, or. when used in the cc file, it is defined in an unnamed namespace, or the static Association is used to restrict the scope of the variable.
Remember, static member variables are regarded as global variables, so they cannot be of the class type!
Translator: This article mainly mentions some of the scope rules, which are summarized as follows:
1. The anonymous namespace in cc can avoid naming conflicts and limited scopes, and avoid directly using the using prompt to pollute the namespace;
2. Nested classes comply with the local usage principle, but they cannot be pre-declared in other header files. Do not make them public;
3. Try not to use global functions and global variables, consider the scope and namespace restrictions, and try to form a compilation unit separately;
4. Do not use the class type (including STL containers) for global variables (including static member variables) in multithreading to avoid bugs caused by ambiguous behaviors.
In addition to name contamination and readability, the scope is mainly used to reduce coupling and improve compilation and execution efficiency.