Detailed explanation of const qualifier summary in C / C + +

Time:2021-11-29

Const qualifier

Const is a qualifier. The value of a variable defined by const cannot be changed.

Const initialization

Since const cannot be changed once it is created, we must initialize it

const int a;// Error, const variable must be initialized!
const int b=10;// Correct, compile time initialization
const int c=get_ size();// Correct, runtime initialization

When variables of the same type are initialized to each other, we can copy each other at will regardless of whether the variables are limited by const. Because we only use the right value attribute of the variable on the right side of the equation in the copy process, we don’t care whether it can be changed.


int m = 5;
const int n = m;
int j = n;

Const and pointer

Top const and bottom const

For pointers, there are three different const cases because they point to another piece of memory, namely:

  1. Pointer to constant (const int *)
  2. Constant pointer (int * const)
  3. Constant pointer to constant (const int * const)

We generally call those that conform to the first case as having the underlying const attribute.

In the second case, it has the top-level const attribute.

The third situation is both.

On the mutual assignment (or initialization) of pointers with const

  • The top-level const does not affect the mutual copying of variables (because the top-level const only ensures that its own value will not change, const does not change its own variable type, and only uses the right value of this type when copying).
  • If the lower const is on the right of the equal sign, the left of the equal sign must be the same lower const (or the type on the right of the equal sign can be converted to the type on the left of the equal sign). Otherwise, the expression cannot be compiled.

Some ideas about the bottom and top const

The underlying and top-level properties of const seem to exist only on pointers. However, there are such codes and comments in C + + Primer:

const int ci=1,&cr=ci;
auto b=ci;// B is an integer (the top const feature of Ci is ignored)
auto c=cr;// C is an integer (CR is the alias of Ci, and CI itself is a top-level const)

This code is to show that the auto specifier generally ignores the feature of the top-level const, and clearly states in the comment that CI itself is a top-level const.

This is also consistent with my view that the bottom and top const are not unique to the pointer. As long as the object that cannot change itself has the top const, and the object that cannot change the object it points to has the bottom const.

From this perspective, a reference actually comes with a top-level const.

Implicit conversion of underlying const

As mentioned above, only the types on the right and left of the equal sign have the same underlying const attribute can be assigned or initialized.

However, sometimes the right side of the equal sign may not have the same underlying const as the left side of the equal sign, but it can still be established. This is because the type on the right side of the equal sign has an implicit conversion, so it has the same underlying const attribute as the type on the left side of the equal sign.

For example:

int i=5;
int *p=&i;
Const int * CP = P // int * implicit conversion is called const int*

Why is it legal to convert int to const int? Because the user’s permission becomes smaller in the process of converting int to const int, and the program will not become unreliable in this process.

From this, we can know that the pointer of non underlying const can be transformed into underlying const by implicit conversion.

Const and reference

You can bind references to const variables, called const references, and references to constants.

Unlike ordinary references, a reference to a constant cannot be used to modify the object it is bound to

const int ci=5;
const int &r=ci;
R = 6 // the error cannot be modified through constant reference
Int & R2 = CI // error, trying to make a non constant reference point to a constant object.

Initialization of const reference

We know that for references, an object must be initialized when initializing, and the type of the object must match it.

However, const’s reference is an exception. When initializing a constant reference, it is allowed to use any expression as the initial value, as long as the result of the expression can be converted into the type of reference, or even bind a non constant object, literal or expression for a constant reference.

int i=42;
const int &r1=i;// Allow const int & to be bound to a normal int object
const int &r2=3.14;// Correct: R2 is a constant reference
const int &r3=r1*2;// Correct: R3 is a constant reference
int &r4 =r1*2;// Error, non constant references cannot be initialized with expressions

The reasons for this are given in C + + Primer:

The easiest way to understand the reason for this exception is to figure out what happens when a constant reference is bound to another type:


double dval=3.14;
const int &ri=dval;

Here RI refers to a number of type int. The operation on RI should be an integer operation, but dval is a double precision floating-point number rather than an integer. Therefore, in order to ensure that RI is bound to an integer, the compiler changes the above code into the following form:

const int temp=dval;// Generates a temporary integer constant from a double precision floating-point number
const int &ri=temp;// Let RI bind this temporary quantity

In this case, RI binds a temporary quantity object. The so-called temporary quantity object is an unnamed object temporarily created when the compiler needs a space to temporarily store the evaluation results of the expression. C + + programmers often refer to temporary quantity objects as temporary quantities.

Const and auto type specifiers

Auto type specifier is a new type specifier introduced in C + + 11, which can automatically infer types.

The auto type inferred by the compiler is sometimes not exactly the same as the type of the initial value. The compiler will appropriately change the result type to make it more consistent with the initialization rules.

When auto infers objects with const, the compiler will generally ignore the top const, while the bottom const will be retained. In addition, for references, because there is no real entity in the reference, if you use a reference to initialize the auto type, auto is actually the type of the object pointed to by the reference, not the reference. If you want to explain that it is a reference type, you need to use auto &.

const int ci=i,&cr=ci;
auto b=ci;// B is an integer (the top const feature of Ci is ignored)
auto c=cr;// C is an integer (CR is the alias of Ci, and CI itself is a top-level const)
auto d=&i;// D is an integer pointer (the address of an integer is a pointer to an integer)
auto e=&ci;// E is a pointer to an integer constant (addressing a constant object is an underlying const)

If you want to infer that the auto type is a top-level const, you need to specify:

const auto f=ci;// The deduction type of Ci is int, and F is const int.

summary

The above is a summary of the const qualifier in C / C + + introduced by Xiaobian. I hope it will be helpful to you. Thank you very much for your support for the developeppaer website!