In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-01-19 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/03 Report--
Editor to share with you the C++ memory model and namespace example analysis, I believe that most people do not know much about it, so share this article for your reference, I hope you will learn a lot after reading this article. Let's take a look at it!
1. Separate compilation
Like the C language, C++ allows and even encourages programmers to put components in separate files. You can compile these files separately and then connect them into executable programs. Typically, the C++ compiler compiles programs and manages connectors. If you modify only one file, you can just recompile the file and then link it to the compiled version of the other file. This makes it easier to manage large programs.
C++ developers use # include to import the header file, and instead of adding the structure declaration to each file, put it in the header file and then include the header file in each source code file. In this way, when you want to modify the structure declaration, you only need to make a change in the header file. In addition, you can put the function prototype in the header file. Therefore, the original program can be divided into three parts.
Header files: prototypes of functions that contain structure declarations and functions that use them
Source code files: code that contains functions related to structures
Source code file: contains code that calls structure-related functions
Do not put function definitions or variable declarations in the header file. This may be feasible for simple situations, but it usually leads to trouble. For example, if you include a function definition in a header file, and then include the header file in two other files, the same program will contain two definitions of the same function, and unless the function is inline, an error will occur. The contents that are often included in the header file are listed below.
Function prototype
Symbolic constants defined using # define or const
Structure declaration
Class declaration
Template declaration
Inline function
It is OK to put the structure declaration in the header file because they do not create the variable, but simply tell the compiler how to create the structure variable when it is declared in the source code file. Similarly, template declarations are not the code to be compiled, they instruct the compiler if and generate a function definition that matches the function call in the source code. Data and inline functions declared as const have special link properties, so they can be placed in the header file without causing problems.
Header file management
You can only include the same header file once in the same file. There is a standard Cmax Cobb + technique that avoids including the same header file multiple times. It is based on the preprocessor compilation instruction # ifndef, or if not defined. The following code snippet means that statements between # ifndef and # endif are processed only if the preprocessor compilation instruction # define is not previously used to define the name COORDIN_H_:
# ifndef COORDIN_H_...#endif
Typically, you use the # define statement to create a symbolic constant, as follows:
# define MAXIMUM 4096
However, as long as # define is used for the name, it is sufficient to define the name as follows:
# ifndef COORDIN_H_#define COORDIN_H_// place include file contents here#endif
Links to multiple libraries
The C++ standard allows each compiler designer to implement name decorations as he sees fit, so binary modules (object code files) created by different compilers are most likely not linked correctly. That is, the two compilers will generate different decorated names for the same function. The difference in name prevents the linker from matching a function call generated by one compiler with a function definition generated by another compiler. When linking a compilation module, make sure that all object files or libraries are generated by the same compiler. If the source code is available, you can usually recompile the source code with your own compiler to eliminate link errors.
two。 Storage persistence, scope and linkability
Next, how the extended storage category affects the sharing of information between files. C++ uses three (four in Clippers 11) different schemes to store data, the difference being how long the data stays in memory.
Automatic storage persistence: the storage persistence of variables (including function parameters) declared in the function definition is automatic. They are created when the program starts executing the function or block of code to which it belongs, and when the function or block of code is executed, the memory they use is freed. C++ has two kinds of variables that store persistence as automatic.
Static storage persistence: both variables defined outside the function definition and variables defined using the keyword static are static. They exist throughout the running of the program. C++ has 3 variables that are persistent and static.
Thread storage persistence: multicore processors are common today, and these CPU can handle multiple execution tasks at the same time. This allows the program to place calculations in different threads that can be processed in parallel. If a variable is declared using the keyword thread_local, its declaration period is as long as the thread to which it belongs.
Dynamic storage persistence: memory allocated with the new operator will remain until it is freed using the delete operator or the program ends. The storage of this kind of memory is dynamic, sometimes referred to as free storage or heap.
2.1 scope and links
Scope describes the extent to which the name is visible in the file. For example, variables defined in a function can be used in that function, but not in other functions, while variables defined before the function definition in the file can be used in all functions. Linkage describes how names are shared between different units. External names can be shared between files, while internal names can only be shared by functions in one file. The names of automatic variables are not linked because they cannot be shared.
C++ variables have a variety of scopes. A variable with a local scope is only available in the code block in which it is defined, which is a series of statements surrounded by curly braces.
The scope of a C++ function can be the entire class or the entire namespace (including global), but it cannot be local (because a function cannot be defined within a block of code, if the scope of a function is local, it is only visible to itself and therefore cannot be called by other functions. Such a function will not run).
2.2 automatic storage persistence
By default, the storage of function parameters and variables declared in the function is automatic, the scope is local, and there is no linkage. That is, if a variable named texas is declared in main () and a variable named texas is declared in the function oil (), two separate variables are created-- they can only be used in the function that defines them. Anything done by the texas of heap iol () does not affect the texas in main (), and vice versa. In addition, memory is allocated to these variables when the program starts executing the block of code to which they belong; when the function ends, the variables disappear.
Use auto in Clippers 11
In caching 11, the keyword auto is used for automatic type inference. However, in the C language and previous C++ versions, the meaning of auto is quite different. It is used to explicitly indicate that the variable is automatically stored:
Int froob (int n) {auto float ford; / / ford has automatic stroage...}
Because keywords can only be used for variables that default to automatic, programmers rarely use it. Its main purpose is to indicate that the current variable is a local automatic variable. In Category 11, this usage is no longer legal.
1, initialization of automatic variables
You can initialize an automatic variable with any expression whose value is known at the time of declaration, and the following example initializes the variable x _ journal _ y _ z:
Int winterint xroom5umbint big = INT_MAX-1int yellowx * x poliint yellow2insecxitcin > > wintint zodiac 3roomw
2, initialization of automatic variables
Understanding how a typical C++ compiler implements automatic variables contributes to a deeper understanding of automatic variables. Because the number of automatic variables increases or decreases with the beginning and end of the function, the program must manage automatic variables at run time. A common method is to set aside a piece of memory and treat it as a stack to manage the increase or decrease of variables. It is called a stack because the new data is symbolically placed on top of the original data (that is, in adjacent memory units, not in the same memory unit) and is removed from the stack when the program has finished using it. The default length of the stack depends on the implementation, but the compiler usually provides the option to change the stack length. The program uses two pointers to track the stack, one to the bottom of the stack-the start of the stack, and the other to the top of the stack-the next available memory unit. When a function is called, its automatic variable is added to the stack, and the pointer at the top of the stack points to the next available memory unit after the variable. At the end of the function, the top pointer on the stack is reset to the value before the function was called, freeing up the memory used by the new variable.
LIFO (last in first out) on the stack, that is, the last variable added to the stack is popped up first. This design simplifies parameter transfer. The function call places the value of its parameters at the top of the stack and then resets the top pointer. The called function determines the address of each parameter based on its parameter description. In the following figure, when the function fib () is called, a 2-byte int and a 4-byte long are passed. These values are added to the stack. When fib () starts execution, it associates real and tell with these two values. When fib () ends, the pointer at the top of the stack points back to the previous location. The new values are not deleted, but are no longer marked, and the space they occupy will be used by the next function call that adds the value to the stack.
3, register variable
The keyword register was originally introduced by the C language, which recommends that compilers use CPU registers to store automatic variables:
Register int count_fast; / / request for a rregister variable
This is designed to increase the speed of accessing variables.
Before Clipper 11, the usage of this keyword in C++ remained the same, but as the hardware and compiler became more and more complex, this hint indicates that variables are used a lot, and the compiler can do something special with them. In cue 11, this prompt is also lost, and the editor case register simply explicitly points out that the variable is automatic. Since the keyword register can only be used for variables that are already automatic, the only reason to use it is to indicate that the programmer wants to use an automatic variable, which may have the same name as an external variable. This is exactly the same as the previous use of auto. However, an important reason to retain the keyword register is to avoid illegal existing code that uses the keyword.
2.3 static persistent variable
Like C, C++ provides three kinds of linkability for statically storing persistent variables: external linkability (accessible in other files), internal linkability (accessible only in the current file), and unlinkability (accessible only in the current function or block of code). These three kinds of links exist throughout the execution of the program, and they have a longer life than automatic variables. Because the number of static variables is constant while the program is running, the program does not need to use special devices, such as stacks, to manage them. The compiler allocates fixed blocks of memory to store all static variables that persist throughout the execution of the program. In addition, if the static variable is not explicitly initialized, the compiler will set it to 0. By default, static arrays and structures set all bits of each element or member to 0.
Create an external static persistence variable and declare it outside the code block
Create an internal static persistence variable, declare it outside the code block, and use the static qualifier
Create an unlinked static persistent variable, declare it in the code block, and use the static qualifier.
... int global = 1000; / / static duration, external linkagestatic int one_file = 50; / / static duration, internal linkageint main () {...} void funct1 (int n) {static int count = 0; / / static duration, no linkageint llama = 0;}
All static persistent variables have the following initialization characteristics: all bits of uninitialized static variables are set to 0. This variable is called zero initialization (zero-initialized).
Table 9.1 summarizes the initialization features used before the introduction of namespaces. Two uses of the keyword static are pointed out, but the meanings are somewhat different: for local declarations to indicate that variables are unlinked static variables, static represents storage persistence; and for declarations outside the code block, static represents internal linkability, and variables are already static persistence. Some people call it keyword overloading, that is, the meaning of a keyword depends on the context.
2.4 static persistence, external connectivity
Variables that are externally linked are often called external variables, and their storage persistence is static and scoped to the entire file. External variables are defined outside the function, so they are external to all functions. For example, you can define them before main () or in the header file. You can use it in any function that follows the definition of an external variable in the file, so an external variable is also called a global variable.
1, single definition rule
On the one hand, it must be declared in every file that uses an external variable; on the other hand, C++ has a "single definition rule" (One Definition Rule, ODR), which states that a variable can only be defined once. To meet this need, C++ provides two kinds of variable declarations. One is a definition declaration or abbreviation definition, which allocates storage space to a variable; the other is a reference declaration or abbreviation declaration, which does not allocate storage space to a variable because it refers to an existing variable.
The reference declaration uses the keyword extern and is not initialized; otherwise, it is declared as defined, resulting in the allocation of storage space.
Double up; / / definition, up is 0extern int blem; / / blem defined elsewhereextern char gr = 'zonal; / / definition because initialized
If you want to use an external variable in multiple files, you only need to include the definition of the variable in one file (a single definition rule), but in all other files that use the variable, you must declare it with the keyword extern.
Global and local variables
Now that you can choose to use global or local variables, which one should you use? First of all, global variables are attractive-- because all functions can access global variables, you don't have to pass parameters. But the cost of easy access is high-the program is unreliable. Computational experience shows that the more the program can avoid unnecessary access to the data, the more it can maintain the integrity of the data. In general, local variables should be used, data should be passed only when knowledge is needed, and global variables should not be used indiscriminately to make data available.
2.5 static persistence, internal connectivity
When you use the static qualifier for a variable with a scope of the entire file, the variable will be linked internally. In a multi-file program, the difference between internal and external linkability is significant. Variables that are internally linked can only be used in the file to which they belong, but regular external variables have external linking, that is, they can be used in other files.
You can use external variables to share data between different parts of a multi-file program; you can use linkability to share data for internal static variables between multiple functions in the same file (namespaces provide another way to share data). In addition, if you make a variable that is scoped to the entire file static, you do not have to worry about its name conflicts with variables in other files that are scoped to the entire file.
2.6 static storage persistence, no connectivity
Unlinked local variables are created this way, using the static qualifier for variables defined in the code block. When you use static in a code block, it causes the storage of local variables to persist static. This means that although the variable is only available in the code block, it still exists when the code block is not active. Therefore, the value of the static local variable remains the same between the two function calls. (static variables apply to regeneration). In addition, if static local variables are initialized, the program initializes only once at startup. When the function is called later, it will not be initialized again like an automatic variable.
2.7 specifiers and qualifiers
Some C++ keywords, called storage specifiers or cv- qualifiers, provide additional information about the storage. The following is the storage specifier:
Auto (no longer a specifier in Clippers 11)
Register
Static
Extern
Thread_local (new to Clippers 11)
Mutable
Most of them have been introduced, and you cannot use multiple specifiers in the same declaration, with the exception of thread_local, which can be used in conjunction with static or extern. As mentioned earlier, prior to Category 11, you could use the keyword auto in your declaration to indicate that a variable is automatic; however, in clocking 11, auto is used for automatic type inference. The keyword register is used to indicate register storage in the declaration, while in Clippers 11, it only explicitly indicates that the variable is automatic. The keyword static is used in a file-wide declaration to indicate internal linking, and in a local declaration to indicate that the storage of local variables is static. The keyword extern indicates that it is a reference declaration, that is, a variable defined elsewhere. The keyword thread_local indicates that the persistence of a variable is the same as that of the thread to which it belongs. Thread_local variables are to threads what regular static variables are to the entire program. The meaning of the keyword mutable will be interpreted in terms of const, so let's introduce the cv- qualifier before explaining it.
1. Cv- qualifier
Here is the cv qualifier
Const
Volatile
Const is a common cv- qualifier that indicates that after memory is initialized, the program can no longer modify it.
The keyword volatile indicates that even if the program code has not modified the memory unit, its value can change. It sounds mysterious, but in fact it is not. For example, you can point a pointer to a hardware location that contains time or information from a serial port. In this case, the hardware (rather than the program) may modify the contents. Or two programs may influence each other and share data. The purpose of this keyword is to improve the optimization ability of the compiler. For example, if the compiler finds that the program uses the value of a variable twice in several statements, the compiler may not ask the program to look for the value twice, but cache the value in a register. This optimization assumes that the value of the variable does not change between the two uses. If you do not declare the variable as volatile, the compiler will do this optimization, declaring the variable as volatile, which is tantamount to telling the compiler not to do this optimization.
2. Mutable
Now back to mutable. You can use it to indicate that even if the structure (or class) variable is const. One of its members can also be modified. For example:
Struct data {char name [30]; mutable int accesses;...}; const data veep = {"Claybourne Clodde", 0,...}; strcpy (veep.name, "Joye Joux"); / / not allowedveep.accesses++; / / allowed
Veep's const qualifier forbids programs to modify veep members, but access members' mutable specifiers exempt access from this restriction.
3. Talk about const again
In C++ (but not in C), the const qualifier has a slight impact on the default storage type. By default, the global variable is external, but the const global variable is internal, that is, to C++, the global const definition is like using the static specifier
Const int fingers = 10; / / same as static const int fingers = 10 nint main (void) {.}
C + + modifies the rules of constant types to make programmers easier. For example, suppose you put a set of constants in a header file and use the header file in multiple files in the same program. Then the preprocessor will include the contents of the header file in each source file, and all source files will contain definitions similar to the following:
Const int finers = 10 Const char * warning = "Wak!"
If the linkiness of the global const declaration is as external as a regular variable, this will go wrong according to the single definition rule. That is, only one file can contain the previous declaration, while other files must use the extern keyword to provide a reference declaration. In addition, only declarations that use the extern keyword can be initialized:
/ / extern would be required if ocnst had external linkageextern const int fingers; / / can't be initializedextern const char * warning
Therefore, you need to use one set of definitions for one file and another set of declarations for other files. However, because the external definition of const data is internal, you can use the same declaration in all files.
Internal linking also means that each file has its own set of constants, rather than that all files share a set of constants. Each definition is private to the file to which it belongs, which is why the constant definition can be placed in the header file. In this way, as long as the two source code files include the same header file, they will get the same set of constants.
If for some reason the programmer wants the linkability of a constant to be external, he can use the extern keyword to override the default internal linkability.
When a const is declared in a function or code block, its scope is a code block, that is, the constant is available only if the program executes the code in that code block. This means that when you create a constant in a function or block of code, you don't have to worry about its name conflicts with constants defined elsewhere.
2.8 functions and linkability
Like variables, functions are linked, although the range of options is smaller than variables. Like C, C++ does not allow you to define another function in one function, so all storage persistence is automatically static, that is, it exists throughout the execution of the program. By default, functions are externally linked, that is, they can be shared between files.
In fact, the keyword extern can be used in the function prototype to indicate that the function is defined in another file, but this is optional (for the program to find the function in another file, the file must be compiled as part of the program, or a library file searched by the linker). You can also use the keyword static to set the linkability of the function to internal so that it can only be used in one file. You must use this keyword in both the prototype and the function definition.
Static int private (double x);... static int private (double x) {...}
This means that the function is only used in this file, and that functions with the same name can be defined in other files. Like variables, in a file that defines a static function, the static function will override the external definition, so even if a function with the same name is defined externally, the file will still use the static function.
The single definition rule also applies to non-inline functions, so the program can contain only one definition for each non-inline function, which means that in a multi-file program, only one file (which may be a library file, not what you provide) contains the definition of the function, but every file that uses the function should contain its function prototype.
Inline functions are not bound by this rule, which allows programmers to put the definition of inline functions in the header file. In this way, each file that contains the header file has an inline function definition. However, C++ requires that all inline definitions of the same function be the same.
2.9 language connectivity
Another form of connectedness, called linguistic connectedness, also affects functions. The linker requires each different function to have a different symbolic name. In C, a name corresponds to only one function, so this is easy to implement. To meet internal requirements, C language compilers may translate function names such as spiff to _ spiff. This method is called C-cause linking. However, in C++, the same name may correspond to multiple functions, and these functions must be translated into different symbolic names. Therefore, the C++ compiler performs name correction or name modification to generate different symbolic names for overloaded functions. For example, you might convert spiff (int) to _ spoff_i and spiff (double, double) to _ spiff_d_d. This method is called C++ language links.
When the linker looks for a function that matches the C++ function call, it uses a different method from the C language. But what happens if you use a precompiled function in the C library in a C++ program? For example, suppose you have the following code
Spiff (22); / / want spiff (int) from a C library
Its symbolic name in the C library file is _ spiff, but for our hypothetical linker, the C++ query convention looks for the symbolic name _ spiff_i. To solve this problem, you can use a function prototype to indicate the convention to use:
Extern "C" void spiff (int); / / use C protocol for name look-upextern void spoff (int); / / use C++ protocol for name look-upextern "C++" void spaff (int); / / use C++ protocol for name look-up
The first prototype uses C language connectedness; the latter two use C++ language connectedness. The second prototype points this out by default, while the third explicitly points it out.
C and C++ connectedness are specifiers developed by the C++ standard, but the implementation can provide other language linkability specifiers.
2.10 Storage scheme and dynamic allocation
The five scenarios that C++ uses to allocate memory to variables (including arrays and structures), except thread memory, are not suitable for memory allocated using the C++ operator new (or C function malloc ()), which is called dynamic memory. Dynamic memory operators are controlled by new and delete, not by scope and linking rules. Therefore, dynamic memory can be allocated in one function and freed in another. Unlike automatic memory, dynamic memory is not LIFO, and the order in which it is allocated and released depends on when and how new and delete are used. Typically, compilers use three separate blocks of memory: one for static variables, one for automatic variables, and the other for dynamic storage.
Although the storage scheme concept does not apply to dynamic memory, it applies to automatic and static pointer variables used to track dynamic memory. For example, suppose you include the following statement in a function:
Float * p_free = new float [20]
The 80 bytes of memory allocated by new (assuming 4 bytes of float) will remain in memory until it is freed using the delete operator. However, when the block of statements containing the declaration is finished, the p_fees pointer disappears. If you want another function to be able to use these 80 bytes of memory, you must pass or return its address to that function. On the other hand, if you declare the linkiness of p_fees as external, all functions in the file that follow that declaration can use it. In addition, the pointer can be used in another file by using the following declaration:
Extern float * p_fees
1. Initialize using the new operator
What if you want to initialize dynamically assigned variables? In Category 98, it is sometimes possible to do this, and Category 11 increases other possibilities.
If you want to allocate storage space and initialize a built-in scalar type, such as int or double, add the initial value after the type name and enclose it in parentheses:
Int * pi = new int (6); double * pd = new double
This parenthesis syntax also has classes that can be used for constructors, which will be described later in this book.
However, to initialize a regular structure or array, you need to initialize it with a list of curly braces, which requires the compiler to support Category 11. Clear11 allows you to do this:
Struct where {double x; double y; double z;}; where * one = new where {2.5,5.3,7.2}; / / C++11int * ar = new int [4] {2, 4, 6, 7}; / / Clearing 11
You can also initialize a list for a single-valued variable in Clippers 11:
Int * pin = new int {}; double * pdo= new double {99.99}
2. When new fails
New may not find the requested amount of memory. In the first 10 years, C++ gave new a null pointer in this case, but now it will raise a std::bad_alloc.
3. New: operators, functions, and substitution functions
The operators new and new [] call the following functions, respectively:
Void * operator new (std::size_t); / / used by newvoid * operator new [] (std::size_t) / / used by new []
These functions are called allocation functions, and they are located in the global namespace. There are also release functions called by delete and delete []:
Void operator delete (void *); void operator delete [] (void *)
4. Locate the new operator
Typically, new is responsible for finding a block of memory in the heap that is sufficient to meet the requirements. There is another variant of the new operator, called the positioning new operator, which allows you to specify the location to use. Programmers may use this feature to set up their memory management rules, deal with hardware that needs to be accessed through a specific address, or create objects in a specific location.
To use the positioning new feature, you first need to include the header file new, which provides a prototype of this version of the new operator; then use the new operator to provide the parameters that provide the desired address. The syntax is the same as the regular new operator, except that you need to specify parameters. Specifically, using the positioning new operator, variables can be followed by square brackets or not. The following demonstrates the four uses of the new operator:
# include struct chaff {char dross [20]; int slag;}; char buffer1 [50]; int * p3, * p4; / / first, the regular forms of new p1 = new chaff; / / place structure in heap p3 = new int [20]; / / place int array in heap / / now, the two forms of placement new p2 = new (buffer1) chaff; / / place structure in buffer1 p4 = new (buffer2) int [20]; / / place int array in buffer2.
For simplicity, this example uses two static arrays to provide memory space for locating the new operator. Therefore, the above code allocates space from the buffer1 to the structure chaff and from the buffer2 to an int array of 20 elements.
3. Namespace
In C++, names can be variables, functions, structures, or enumerations. Classes and members of classes and structures. As the project grows, so does the possibility of conflicting names. When using class libraries from multiple vendors, it may result in name conflicts. For example, both libraries might define classes named List, Tree, and Node, but in an incompatible manner. Users may want to use the List class of one library and the Tree class of another library. This conflict is called a namespace problem.
The C++ standard provides namespace tools to better control the scope of names. It took a while for the compiler to support namespaces, but it is now common.
3.1 traditional C++ namespace
Before introducing the new namespace features in C++, review the existing namespace attributes and concepts in C++.
Declare the area. The declaration area is the area in which you can declare it. For example, you can declare a global variable outside the function, and for such a variable, the declaration area is the file in which it is located. For a variable declared in a function, the declaration area is the block of code in which it is declared.
Potential scope. The potential scope of a variable starts at the declaration point and ends at the end of its declaration area. Therefore, the potential scope is smaller than the declaration area, because variables must be defined before they can be used.
However, variables are not visible anywhere within their potential scope. For example, it might be hidden by a variable of the same name declared in another nested declaration area. For example, local variables declared in a function will be hidden in global variables declared in the same file. The scope in which a variable is visible to a program is called a scope.
C++ 's rules for global and local variables define a namespace hierarchy. Each declaration area can declare names that are independent of the names declared in other declaration areas. Local variables declared in one function do not conflict with local variables declared in another function.
3.2 New namespace features
C++ has added a feature to create named namespaces by defining a new declaration area, one of the purposes of which is to provide a region for declaring names. A name in one namespace does not conflict with the same name in another namespace, while allowing other parts of the program to use what is declared in that namespace.
Namespaces can be global or in another namespace, but not in a code block. Therefore, by default, the linking of names declared in the namespace is external.
In addition to user-defined namespaces, there is another namespace-- the global namespace. It corresponds to the file-level declaration zone, so the global variable mentioned earlier is now described as being in the global namespace.
Names in any namespace do not conflict with names in other namespaces. The declaration and definition rules in the namespace are the same as the global declaration and definition rules.
Namespaces are open, that is, you can add namespaces to existing namespaces. The following statement adds the name goose to the list of names already in Jill:
Namespace Jill {char * goose (const char *);}
Again, the original Jack namespace provides a prototype for the fetch () function. You can use the Jack namespace again after this file (or in another file) to provide the code for the function:
Namespace Jack {void fetch () {...}}
Of course, there needs to be a way to access names in a given namespace. The easiest way is to use the namespace to qualify the name through the scope parsing operator::
Jack:: pail = 12.34; / / use a variableJill::Hill mole; / / create a type Hill structureJack::fetch (); / / use a function
Undecorated names are called unqualified names; names that contain namespaces are called qualified names.
1. Using declaration and using compilation directive
C++ provides two mechanisms, the using declaration and the using compilation directive, to simplify the use of names in namespaces. The using declaration makes specific identifiers available, and the using compilation directive makes the entire namespace available.
The using declaration consists of the qualified name and the keyword using before it, and the using declaration adds a specific name to the declaration area to which it belongs.
The using declaration makes one name available, while the using compilation directive makes all names available. The using compilation instruction, which consists of a namespace name and the keyword using namespace before it, makes all names in the namespace available without using the scope resolution operator.
Using the using compilation directive in the global declaration area makes the name of the namespace available globally. Using the using compilation instruction in a function makes the name in it available in the function.
2. Comparison between using compilation instructions and using declarations
Using the using compilation directive to import all names in a namespace is not the same as using multiple using declarations, but more like heavy use of scope resolution operators. When using a using declaration, it is as if the corresponding name has been declared. If a name is already declared in the function, you cannot import the same name with the using declaration. However, when you use the using compilation directive, name resolution occurs, just as if the name was declared in the minimum declaration area that contains the using declaration and the namespace itself.
Note: assume that the namespace and the declaration area define the same name. If you try to import the name of the namespace into the declaration area using the using declaration, the two names will conflict, resulting in an error. If you import the name of the namespace into the declaration area using the using compilation directive, the local version hides the layer namespace version.
In general, using the using declaration is safer than using the using compilation instruction because it imports only the specified name. If the name conflicts with the local name, the compiler issues an instruction. The using compilation directive imports all names, including names that may not be needed. If there is a conflict with the local name, the local name overrides the namespace version and the compiler does not issue a warning. In addition, the openness of namespaces means that the names of namespaces can be scattered in multiple places, which makes it difficult to know exactly what names have been added.
3. Other properties of namespaces
You can nest namespace declarations:
Namespace elements {namespace fire {int flame;...} float water;}
4. Unnamed namespace
You can create an unnamed namespace by omitting the name of the namespace
Namespace / / unnamed namespace {int ice; int bandycoot;}
This is like being followed by the using compilation instruction, that is, the potential scope of the name declared in the namespace is: from the declaration point to the end of the declaration area. In this respect, they are similar to global variables. However, because this namespace does not have a name, you cannot explicitly use using compilation instructions or using declarations to make it available elsewhere. Specifically, you cannot use a name in an unnamed namespace in a file other than the one to which it belongs. This provides an alternative to internal static variables for linkability.
3.3 Namespace and its Future
As programmers become familiar with namespaces, a unified programming philosophy will emerge. Here are some current guidelines.
Use variables declared in a named namespace instead of external global variables.
Use variables declared in a named namespace instead of static global variables.
If you develop a function library or class library, put it in a namespace. In fact, C++ currently advocates putting standard function libraries in the namespace std, which extends to functions from the C language. For example, the header file math.h is C-compatible and does not use namespaces, but the C++ header file cmath should put various math library functions in the namespace std. In fact, not all compilers have completed this transition.
Use only the compilation instruction using as a stopgap way to convert old code to use namespaces.
Do not use using compilation directives in header files. First, this masks which names you want to make available; in addition, the order in which the header files are included may affect the behavior of the program. If you do not want to use the compilation instruction using, you should place it after all preprocessor compilation instructions # include.
When importing names, it is preferred to use the scope resolution operator or the method declared by using.
For using declarations, it is preferred to set its scope to local rather than global.
The purpose of using namespaces is to simplify the management of large programming projects. For simple programs with only one file, it is not rebellious to use using compilation instructions.
These are all the contents of the article "sample Analysis of memory models and namespaces in C++". Thank you for reading! I believe we all have a certain understanding, hope to share the content to help you, if you want to learn more knowledge, welcome to follow the industry information channel!
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.