66

What does const at "top level" qualifier mean in C++?

And what are other levels?

For example:

int const *i;
int *const i;
int const *const i;
Glenn Teitelbaum
  • 10,108
  • 3
  • 36
  • 80
user103214
  • 3,478
  • 6
  • 26
  • 37

4 Answers4

65

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).

legends2k
  • 31,634
  • 25
  • 118
  • 222
James Kanze
  • 150,581
  • 18
  • 184
  • 329
  • 9
    One other point: when writing functions the top-level qualifiers of arguments are discarded. This means that `void foo(char const)` and `void foo(char)` are the same function (and in fact they can be interchanged). The reasoning is that since the argument is taken by copy, the caller does not care whether the copy can be modified or not, so it's transparent for her. – Matthieu M. Oct 27 '11 at 11:30
  • 8
    @MatthieuM. Good point, although not exactly true as stated. The top-level qualifiers are ignored in a declaration, and in the type of the function. In the definition, however, they still behave as usual within the function. (Top level qualifiers are also ignored by `typeid` and template parameters, when matching exceptions to catch, and probably in some other cases I've forgotten. In practice, they also have no effect on non-class type return values.) – James Kanze Oct 27 '11 at 12:51
  • Regarding the last example with `const p`: `p=0;` is an attempt to change `p`, but it doesn't have undefined behavior, it's just ill-formed. – Ruslan Jan 11 '16 at 12:23
15

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!!!

Eugenio
  • 244
  • 2
  • 13
Aditya Raj
  • 327
  • 3
  • 14
  • 1
    Thanks a lot, that is the most clear explanation.By the way C++ Primer is the book which lead me here. – Aghiad Alzein Feb 26 '21 at 04:50
  • 1
    "You should look at top and low level const through references and pointers, because this is where they are relevant". Ok but nobody never show an example with references – openyourmind Jan 07 '22 at 00:24
13

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
Glenn Teitelbaum
  • 10,108
  • 3
  • 36
  • 80
13

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.

Blagovest Buyukliev
  • 42,498
  • 14
  • 94
  • 130
  • 1
    Excellent and clear answer. P.S. `int const *i` equals to `const int *i` (all are low-level const). I use `const int *i` (low-level) to distinguish its const level more often from `int *const i` (top-level). – dotslash Apr 17 '17 at 09:08
  • I'm struggling to understand "Whenever const appears immediately before or after the type of the identifier, that is considered a top-level qualifier." Does this not apply to `int const *i` because the `const` appears in the middle of the type of the identifier, which is in this case is `int *`? – 24n8 Aug 21 '20 at 04:37
  • @24n8 I am also struggling to understand – openyourmind Jan 07 '22 at 00:18