Mutable keyword
Keyword Mutable is a non-commonly used keyword in C . He can only use non-statically and very quantity data members. We know that an object's status is determined by the object's non-static data member, so as data members change The status of the object will also change!
If a member function of a class is declared as a const type, it means that the function does not change the status of the object, that is, the function does not modify the category of non-static data members. But sometimes need to be a data member of the class in this class function. Take assignment. This time you need to use the Mutable keyword.
For example: class demo {public: demo () {} ~ demo ()} public: BOOL getFlag () const {m_naccess ; return m_bflag;} private: int m_naccess; bool m_bflag;};
INT main () {return 0;}
Compile The above code will appear Error C2166: L-Value Specifies Const Object Ob Description Changes the category non-status data member in the Const type function.
At this time, Mutable needs to be used to modify the non-static data member M_NAccess to change in the Const member function, the code is as follows:
Class demo {public: Demo () {} ~ demo ()} public: BOOL getFlag () const {m_naccess ; return m_bflag;} private: mutable int m_naccess; Bool M_bflag;};
INT main () {return 0;}
This will not have a mistake when it is recompiled!
Volatile keyword
Volatile is a freshly known keyword in C / C , which tells the compiler that do not hold a temporary copy of the variable, which can be applied to basic types such as int, char, long ... also applies to C The structure of C and C . All members of the structure or class will be considered volatile when the structure or class object is modified with Volatile.
Using Volatile does not negate the need for synchronization objects such as critical_section, mutex, event, for example: int i; i = i 3; no matter how, there will always be a short period of time, I will be placed in a register because arithmetic operations Can only be done in the register. In general, the volatitle keyword is for rows between rows, not in the line.
Let's first implement a simple function to observe the deficiencies in the assembly code produced by the compiler, and observe how the volatile keyword fixes this deficiencies. There is a busy loop in this function (so-called busy loop is also called busy waits, is a highly waste CPU time cycle method)
Void getKey (char * pch) {while (* pch == 0);}
When you close the optimization option in the VC development environment, compile this program (assembly code); while (* pch == 0) $ l27; load the address stored in Pch Mov Eax, DWORD PTR _PCH $ [EBP]; Load The Character Into The Eax Register Movsx Eax, Byte Ptr [EAX]; Compare The Value To Zero Test Eax, Eax; if Not Zero, EXIT LOOP JNE $ L28; JMP $ 1 $ L28;}
This unopened code continuously loads the appropriate address, the contents of the address, the test result. The efficiency is quite low, but the result is very accurate now let's take a look at all the optimization options of the compiler open, recompilate the program, generated assembly code, and what is more different from the code above; {; loading Address Stored In Pch Mov Eax, DWORD PTR _PCH $ [ESP-4]; Load The Character INTO The Al Register Movsx Al, Byte Ptr [Eax]; While (* PCH == 0); Compare The Value In The Al Register To Zero Test Al, Al; IF STILL ZERO, TRY AGAIN JE SHORT $ L84 ;;}
It can be seen from the length of the code, which is much shorter than that is not optimized. It should be noted that the compiler puts the MOV instruction outside the loop. This is a very good optimization in a single-thread, however, in multi-threaded applications, if another thread changes the value of the variable, the loop will never end. The value being tested will always be placed in the register, so the segment code is a huge bug in the case of multithreading. The solution is to rewrite the getKey function and declare the parameter PCH as Volatile, the code is as follows:
Void getKey (Volatile Char * PCH) {while (* pch == 0);}
This modification does not have any effect on non-optimized versions. Please see the optimized results below:
; {; Load The Address Stored in Pch Mov Eax, DWORD PTR _PCH $ [ESP-4]; while (* pch == 0) $ l84:; Directly Compare the value to zero cmp byte ptr [EAX], 0; IF STILL ZERO, TRY AGAIN JE SHORT $ L84 ;;}
This modified result is relatively perfect, the address will not change, so the address declaration is moved outside the loop. The address content is Volatile, so it is constantly reconfined every cycle.
Passing a const volatile variable is passed to a function to function. Such a statement means that the function cannot change the value of the variable, but the value of the variable can be changed by another thread at any time.
Explicit keyword
We basically use the explicit keyword when writing applications, and its role is "Prohibited single parameter constructor" is used for automatic type of conversion, where typical example is the container type, in this type In the constructor, you can pass the initial length as a parameter to the constructor. For example: You can declare such a constructor class array {public: explicit array (int size); ...}; here the expendit key It is a crucial role. If there is no such keyword, this constructor has the ability to convert int to array. Once this happens, you can assign an integer value to the Array without causing any problems, such as: Array Arr; ... arr = 40; At this time, C automatic type conversion will convert 40 into Array with 40 elements, and assigned to Arr variables, this result is not what we want. If we will The constructor declares that EXPLICIT, the above assignment will cause the compiler to report error, so that we can find errors in time. Need not to note: Explicit also prevents "initialization of the transformation operation"; for example: array Arr (40); // Correct Array Arr = 40; // Error
Look at the following two operations: X x; y y (x); // Explicit type conversion to another X x; y y = x; // implicit type conversion
There is a small difference in these two operations. The first way is transformed by explicit type, and a new object of the type Y is generated according to the type of Di X; the second method produces a model y by implicit conversion. The application of the new object .Explicit keyword is mainly the constructor defined above. Refer to the application of the keyword to see the STL source code, where the keyword is used.
__based keyword
This keyword is primarily used to solve some problems related to shared memory, which allows pointers to be defined as 32-bit offset values calculated from a point, rather than the absolute position of internal deposition.
Typedef struct tagdemostruct {int A; char SZ [10];} Demostruct, * pdemostruct;
Handle Hfilemapping = CreateFilemapping (...); lpvoid lpshare = (lpdword) mappviewoffile (...);
Demostruct __based (lpshare) * lpdemo;
The above example declares a pointer LPDEMO, which is stored inside, which is the offset value starting from LPSHARE, that is, the lphead is an offset value based on LPShare. The Demostruct of the above example is just a structure that is cascaded, used to represent Any structure.
Although the __based pointer is very easy, you have to pay a certain price in efficiency. Whenever you use the __based pointer to process data, the CPU must add the base address to the real location.
Here I only introduce the meaning of several keywords that are very common from time to time, and other common keywords introduce their articles a lot there to be here. I hope that these content can be everyone. Have a certain help!