C ++ understand volatile, mutable, const and const mutable

Source: Internet
Author: User

The Chinese meaning of mutalbe is "variable, easy to change", which is the opposite of constant (const in both C ++.
In C ++, mutable is also set to break through the const restrictions. Variables modified by mutable will always be in a mutable state, even in a const function.

We know that if the member function of the class does not change the state of the object, the member function will be declared as const. However, sometimes we need to modify some data members irrelevant to the class status in the const function, so this data member should be modified by mutalbe.

Below is a small example:

Class ClxTest
{
Public:
Void Output () const;
};

Void ClxTest: Output () const
{
Cout <"Output for test! "<Endl;
}

Void OutputTest (const ClxTest & lx)
{
Lx. Output ();
}

The Output function of the ClxTest member function is used for Output and does not modify the status of the class. Therefore, it is declared as const.

The OutputTest function is also used for Output. It calls the Output method of the object lx. To prevent other member functions from being called to modify any member variables, the parameter is also modified by const.

Now, we need to add a function: calculate the number of output times of each object. If the variable used for counting is a common variable, the value of the variable cannot be modified in the Output of the const member function. The variable has nothing to do with the state of the object, therefore, the const attribute of Output should be removed to modify the variable. At this time, our mutable will be available-as long as mutalbe is used to modify this variable, all the problems will be solved.

The modified code is as follows:

Class ClxTest
{
Public:
SClxTet ();
~ ClxTest ();

Void Output () const;
Int GetOutputTimes () const;

Private:
Mutable int m_iTimes;
};

ClxTest: ClxTest ()
{
M_iTimes = 0;
}

ClxTest ::~ ClxTest ()
{}

Void ClxTest: Output () const
{
Cout <"Output for test! "<Endl;
M_iTimes ++;
}

Int ClxTest: GetOutputTimes () const
{
Return m_iTimes;
}

Void OutputTest (const ClxTest & lx)
{
Cout <lx. GetOutputTimes () <endl;
Lx. Output ();
Cout <lx. GetOutputTimes () <endl;
}

The m_iTimes counter is mutable, so it can break through the const limitation and be modified in the function modified by const.

-----------------------

Volatile is a little-known keyword in c/c ++ that tells the compiler not to hold a temporary copy of a variable. It can be applied to basic types.
 
For example, int, char, long... also applies to the structure of C and the class of C ++. When the structure or Class Object is modified using volatile, all the members of the structure or class are considered volatile. Using volatile does not contradict the need for synchronization objects such as CRITICAL_SECTION, Mutex, and Event.
 
For example:
 

Int I;
I = I + 3;
In any case, I will always be placed in a register for a short period of time, because arithmetic operations can only be performed in registers. In general, the volatitle keyword applies to rows rather than rows.
 
Let's first implement a simple function to observe the deficiencies in the compilation code generated by the compiler, and to observe how the volatile keyword fixes the deficiency. There is a busy loop in this function (the so-called busy loop is also called busy waits, which is a high waste of CPU time)
 

Void getKey (char * pch)
{
While (* pch = 0 );
}
After you close all the optimization options in the VC development environment, compile the program and obtain the following results (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 $ L27
$ L28
;}
This section of unoptimized code constantly loads the appropriate address, loads the content in the address, and tests the results. Efficiency is quite low, but the results are very accurate. Now let's take a look at all the compiler's optimization options after the switch is turned on, re-compile the program, the generated assembly code, and the above Code
 
What are the differences?
 

;{
; Load the 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
;
;}
The code length is much shorter than that without optimization. Note that the compiler places the MOV command out of the loop. This is a very good Optimization in a single thread. However, in a multi-threaded application, if another thread changes the variable value, the loop will never end. The tested value is always placed in the register. Therefore, this section of code has a huge BUG in the case of multithreading. Solution: Re-
 
Write the getKey function once and declare the pch parameter as volatile. The Code is as follows:
 

Void getKey (volatile char * pch)
{
While (* pch = 0 );
}
This modification has no impact on the non-optimized version. The following figure shows the results after optimization:
 

;{
; 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
;
;}
The modification results are perfect and the address will not change. Therefore, the address Declaration is moved out of the loop. The address content is volatile, so it is constantly re-checked in each loop. It is legal to pass a const volatile variable as a parameter to the function. Such a declaration 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.
 

Static member functions
There is nothing to say about static member functions.

1. The address of the static member function can be stored by the common function pointer, while the common member function address needs to be stored by the class member function pointer. Example:
Class base {
Static int func1 ();
Int func2 ();
};

Int (* pf1) () = & base: func1; // common function pointer
Int (base: * pf2) () = & base: func2; // member function pointer


2. static member functions cannot call non-static members of a class. Because the static member function does not include the this pointer.

3. static member functions cannot be declared as virtual, const, and volatile functions at the same time. Example:
Class base {www.2cto.com
Virtual static void func1 (); // Error
Static void func2 () const; // Error
Static void func3 () volatile; // Error
};


The last point is that static members can be accessed independently, that is, they can be accessed without creating any object instance.

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.