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
constint ci = 42; // we cannot change ci; const is top-level
constint *p2 = &ci; // we can change p2; const is low-level
constint *const p3 = p2; // right-most const is top-level, left-most is not
constint &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 !
constint *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:
What Lippman et al. are trying to get across is the difference between a pointer to constant and a constant pointer.
- intconst* 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 intconst* 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.
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
constint* 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
constint* const const_ptr_to_const_int = &i ; // const pointer to const int
// const at top-level, const at low-level
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 :/
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).
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.