What are top-level const qualifiers?

Solution 1:

A top-level const qualifier affects the object itself. Others are only relevant with pointers and references. They do not make the object const, and only prevent modification through a path using the pointer or reference. Thus:

char x;
char const* p = &x;

This is not a top-level const, and none of the objects are immutable. The expression *p cannot be used to modify x, but other expressions can be; x is not const. For that matter

*const_cast<char*>( p ) = 't'

is legal and well defined.

But

char const x = 't';
char const* p = &x;

This time, there is a top-level const on x, so x is immutable. No expression is allowed to change it (even if const_cast is used). The compiler may put x in read-only memory, and it may assume that the value of x never changes, regardless of what other code may do.

To give the pointer top-level const, you'd write:

char x = 't';
char *const p = &x;

In this case, p will point to x forever; any attempt to change this is undefined behavior (and the compiler may put p in read-only memory, or assume that *p refers to x, regardless of any other code).

Solution 2:

int *const i puts const at the top-level, whereas int const *i does not.

The first says that the pointer i itself is immutable, whereas the second says that the memory the pointer points to is immutable.

Whenever const appears immediately before or after the type of the identifier, that is considered a top-level qualifier.

Solution 3:

The way it was explained to me, given:

[const] TYPE * [const] VARIABLE

VARIABLE is used to point to data of type TYPE through *VARIABLE

Draw a line through the * or multiple *s

  1. If there is a const to the left of the * it applies to the data and the data cannot be changed: *VARIABLE cannot be assigned, except at initialization
  2. If there is a const to the right of the * it applies to the VARIABLE and what the VARIABLE points to cannot be changed: VARIABLE cannot be assigned, except at initialization

So:

          |              left  right
int       *       i1;
          |              no    no     can change *i1 and i1

int const *       i2;     
          |              yes   no     cannot change *i2 but can change i2

int       * const i3;
          |              no    yes    can change *i3 but i3 cannot be changed

int const * const i4;
          |              yes   yes    cannot change *i4 or i4

Solution 4:

The two levels of const are: * Low-level Const * Top-level Const

You should look at top and low level const through references and pointers, because this is where they are relevant.

int i = 0;
int *p = &i;
int *const cp = &i;
const int *pc = &i;
const int *const cpc = &i;

In the code above, there are 4 different pointer declarations. Let's go through each of these,

int *p: Normal Pointer can be used for making changes to the underlying object and can be reassigned.

int *const cp (top-level const): Const Pointer can be used for making changes to the underlying object but cannot be reassigned. (Cannot change it to point to another object.)

const int *pc (low-level const): Pointer to Const cannot be used for making changes to the underlying object but can itself be reassigned.

const int *const cpc (both top and low-level const): Const Pointer to a Const can neither be used for making changes to the underlying object nor can itself be reassigned.

Also, top-level const is always ignored when assigned to another object, whereas low-level const isn't ignored.

int i = 0;
const int *pc = &i;
int *const cp = &i;

int *p1 = cp; // allowed
int *p2 = pc; // error, pc has type const int*

Hope this helped :) FYI: C++ Primer has a lot of information about the same!!!