A declaration for an object in c++ has the following form :
[Storage class] [Qualifier] Type Name ; /*brackets means optional .*/
For storage classes you can check this tutorial , as for qualifiers , they are used to qualify a definition , as being either a constant definition : const
, or a volatile definition : volatile
, or both a const volatile
definition .
const
and volatile
can be used with variables , functions parameters and return values , class types data members and function members .
const
const
means immutable , no change is to be made for a definition , after a definition has been provided . A constant variable must be initialized .
An example with variables .
int var_i; /*var_i is not a constant variable , its definition can be changed .*/ var_i = 1; int var1_i; /*var1_i is not a constant variable , its definition can be changed .*/ var1_i = 1; const int var_ci = -1 ; /*var_ci is a constant variable , its definition cannot change . var_ci can also be declared int const var_ci = -1 ; */ int const *ptr_ci = &var_i; /*ptr_ci is a pointer to a constant integer , it is illegal to use *ptr_ci = 4 ; to change the value of the pointed to integer .*/ int *const cptr_i = &var_i; /*cptr_i is a constant pointer to an integer . The value of cptr_i cannot be changed . It is illegal to do : cptr_i = &var1_i; .*/ const int *const cptr_ci = &var_i; /*cptr_ci is a constant pointer to a constant integer . The value of the pointer and the pointed value cannot be changed . It is illegal to do : cptr_ci = &var1_i; *cptr_ci = 34; .*/
An example with function parameters .
const int * foo(const int *ptr_ci ){ /*ptr_ci is a pointer to a constant integer , the value of the constant integer must not be changed . The function foo , perform an operation , that does not affect original data .*/ static int arr_i[ ] = {0 , 1 , 2 , 3 }; /*Declare a static array arr_i.*/ return &arr_i[1]; /*Return the address of the second element of the array .*/ }
An example with class data members , and class member functions .
class Foo{ public: const int var_i; float var_f; mutable double var_d; /*A mutable class data member , can be changed , even if its class instance is declared constant .*/ Foo( ); void cFct( )const; }; Foo::Foo():var_i(0 ) , var_f(-1.f ) , var_d(0.4 ){} void Foo::cFct( )const{ /*A constant function can access all data members , but must not change the value of any , beside a data member which is declared mutable .*/ var_d = var_d + var_f + var_i; } int main(void ){ Foo foo; /*Create an object named foo , It is illegal to do foo.var_i = -1 ; because var_i is declared constant .*/ foo.var_d = foo.var_i + foo.var_f + foo.var_d ; /*Assign a value to var_d .*/ foo.cFct(); /*Call the constant function cFct .*/ const Foo foo_c; /*Create an object named foo_c. foo_c is declared constant , it is allowed only to change the value of a mutable data member. It is illegal to do : foo_c.var_f = 4.f ; .*/ foo_c.var_d = foo.var_i + foo.var_f + foo.var_d ; /*Assign a value to var_d , which is a mutable data member .*/ foo_c.cFct(); /*A constant object is only allowed to call constant functions .*/ }
volatile
A volatile
qualifier , is used to inform the compiler , that a variable definition , can change asynchronously to the program . So in a way , which is not related to a change made by the program itself , hence the change to the variable can be made by an external process .
When the volatile qualifier is used , the compiler is not to do certain optimization , that relies on the fact that a change in a variable definition , is synchronous to the program itself . When a variable is accessed , and even if the program itself did not change its value , the value of the variable is to be reread .
member functions which are not static , can be declared volatile , If an instance of a class is volatile , it can only access volatile member functions .
class Foo{ public: volatile int var_vi; float var_f; Foo(); void fct_v( )volatile; void fct(); }; Foo::Foo( ):var_vi(1 ) , var_f(-3.f ){} void Foo::fct_v( )volatile{ var_vi = var_vi + var_f; } void Foo::fct( ){ var_vi = var_vi + var_f; } int main(void ){ Foo foo; /*Create an instance of foo .*/ foo.var_vi = -1; /*Set a value to the volatile data member .*/ foo.fct_v(); /*Call the volatile function .*/ foo.fct(); /*Call the non volatile function .*/ volatile Foo foo_v; /*Create a volatile instance of Foo . Each data member of foo_v is volatile . foo_v can only access functions declared as volatile .*/ foo_v.var_f = 3.1f; /*Set a value to var_f which is not declared volatile .*/ foo_v.fct_v(); /*Call the volatile function fct_v .*/ }
const
can be used with volatile
, to indicate the constance of a variable with regards to the program itself , but the ability of this variable of being changed from outside the program .
const volatile int var_ci = 0 ;