Top level and low level const-s.

So there is something I read in C++ Primer that's confusing me, basically it said
"We use the term top-level const to indicate that the
pointer itself is a const. When a pointer can point to a const object, we refer to that const as a low-level const.

More generally, top-level const indicates that an object itself is const. Top-level const can appear in any object type, i.e., one of the built-in arithmetic types, a class type, or a pointer type. Low-level const appears in the base type of compound types such as pointers or references. Note that pointer types, unlike most other types, can have both top-level and low-level const independently:"


Then it provided this code:

1
2
3
4
5
6
int i = 0;
int *const p1 = &i; // we can't change the value of p1; const is top-level
const int ci = 42; // we cannot change ci; const is top-level
const int *p2 = &ci; // we can change p2; const is low-level
const int *const p3 = p2; // right-most const is top-level, left-most is not
const int &r = ci; // const in reference types is always low-level 


it's just so confusing if someone can explain the 5 lines of code in a better way than the comments beside it, would be very appreciated !



Last edited on
Hi,

It helps to read these right to left:

const int *const p3 = p2; // p3 is a const pointer to const int

A const pointer means it can't be made to point at something else. Obviously const int means the int value cannot change.

References can never be made to refer to something else (this is called re-seating). The way references are implemented is not defined by the standard, but I tend to think of them as being const pointers (they could be implemented that way). Another more general way is to think of a reference as being another name for a variable. This is why references are a valuable thing in modern C++. Prefer to do references rather than pointers.

Good Luck !!

Edit:

I prefer to put pointers and references right next to the type (as opposed to the variable identifier, or in between) - C++ is all about types:

1
2
3
const int* const p3 = p2;

const std::string& MyString = "Fred";

Last edited on
What Lippman et al. are trying to get across is the difference between a pointer to constant and a constant pointer.
- int const* p1 Is a pointer to a constant int
- int *const p2 is a constant pointer to int.

I've never heard the term "top level const" before, but it looks like they are trying to label the const which applies to the (last) pointer as the "top-level" const.

Per their rules int const* p1 isn't "top-level" const because the const applies to the pointed-to-type. On the other hand the const in int *const p2 is "top-level" because the const refers to the pointer.

By "levels" they are referring to layers of indirection.
https://en.wikipedia.org/wiki/Indirection
Last edited on
When we have a pointer that points to an object, there are two objects involved:
a. the pointer object itself, and b. the object that is pointed to.

In the book, 'top-level' const-ness refers to the const-ness of the pointer object;
'low-level' const-ness refers to the const-ness of the object pointed to (when accessed via this pointer).

1
2
3
4
5
6
7
8
9
10
11
12
13
int i = 0 ;

int* ptr_to_int = &i ; // non-const pointer to non-const int
                       // non-const at top-level, non-const at low-level

const int* ptr_to_const_int = &i ; // non-const pointer to const int
                                   // non-const at top-level, const at low-level

int* const const_ptr_to_int = &i ; // const pointer to non-const int
                                   // const at top-level, non-const at low-level

const int* const const_ptr_to_const_int = &i ; // const pointer to const int
                                               // const at top-level, const at low-level 

Another point of confusion is that :

int const* p1 // Is a pointer to a constant int

can be written:

const int* p1 // Is a pointer to a constant int

The first form seems less common, although it does read right to left :+)
Why is the const on the rvalue of the assignment always a low level? like why can't &i ever be a top level const? I see the pointer being top level no matter what :/
Be careful not to confuse rvalues and references.

http://en.cppreference.com/w/cpp/language/reference


There are different categories and types of rvlaues and lvalues:
http://en.cppreference.com/w/cpp/language/value_category

I will (or we?) will track down a link that explains it all very well. There was a short paper by Stroustrup which explained what was what very simply.

Why is the const on the rvalue of the assignment always a low level?
TheIdeasMan wrote:
References can never be made to refer to something else (this is called re-seating).
Last edited on
Found something similar:

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2010/n3055.pdf

Edit:

This was the document I was thinking of ...

http://www.stroustrup.com/terminology.pdf
Last edited on
> I've never heard the term "top level const"

The term that the standard uses (quite liberally) is: "top-level cv-qualifiers".

For instance:
Evaluating a throw-expression with an operand throws an exception; the type of the exception object is determined by removing any top-level cv-qualifiers from the static type of the operand ...

After producing the list of parameter types, any top-level cv-qualifiers modifying a parameter type are deleted when forming the function type.

Any difference in top-level cv-qualification is subsumed by the initialization itself and does not constitute a conversion.
[Example: A parameter of type A can be initialized from an argument of type const A . The implicit conversion sequence for that case is the identity sequence; it contains no “conversion” from const A to A . —end example]

The top-level cv-qualifiers on the template-parameter are ignored when determining its type.
Topic archived. No new replies allowed.