Type qualifiers : const , volatile , in C++ a tutorial
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 ;
Originally published at https://twiserandom.com on January 11, 2021.