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 ;
