Detail the summary of the const qualifier in C and C++

  • 2020-07-21 09:23:57
  • OfStack

const qualifiers

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

Initialization of const

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


const int a;// Error, const Variables must be initialized! 
const int b=10;// Correct, initialized at compile time 
const int c=get_size();// Correct, initialized at run time 

When variables of the same type are initialized with each other, we can arbitrarily copy each other regardless of whether the variables are restricted by const. Because we only use the rvalue property of the variable on the right side of the equation during copying, we don't care if it can be changed or not.


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

const and pointer

Top const vs. bottom const

For Pointers, there are three different const cases due to the fact that they point to another slice of memory, namely:

Pointer to constant (const int *) Constant pointer (int * const) Constant pointer to constant (const int *const)

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

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

The third case is both.

About mutual assignment (or initialization) of Pointers with const

The top-level const does not affect the copying of variables (the reason is that the top-level const only guarantees that its value does not change, const does not change its variable type and only USES the rvalue of that type when copying). If the right side of the equals sign is the bottom const, then the left side of the equals sign must be the same bottom const(or the type on the right side can be converted to the left side), otherwise the expression will not compile.

Some thoughts on the bottom and top const

The bottom and top attributes of const appear to exist only on Pointers. But c++primer has this code and comment:


const int ci=1 . &cr=ci;
auto b=ci;//b is 1 An integer (ci The top of the const The feature is ignored )
auto c=cr;//c is 1 An integer (cr is ci The alias ,ci Itself is 1 A top const)

This code is intended to show that the auto specifier 1 generally ignores the top-level const feature. The comment explicitly states that ci itself is 1 top-level const.

This is also in line with my opinion 1, bottom and top const are not specific to Pointers in fact. Objects that cannot change themselves have top level const, while objects that cannot change themselves point to have bottom level const.

From this perspective, references actually come with top-level const.

Implicit conversion of the underlying const

As mentioned above, you can assign or initialize only types that have the same underlying const property to the right and left of the equal sign.

However, sometimes the right side of the equal sign may not have the same underlying const as the left side, because the type on the right side of the equal sign is implicitly converted to have the same underlying const property as the type on the left side.

Such as:


int i=5;
int *p=&i;
const int *cp=p//int* The implicit transformation is called const int*

Why is the conversion of int to const int set to be legal? Because the user's rights are reduced during the conversion of int to const int. This conversion does not make the program unreliable.

From this we learn that Pointers to non-underlying const can be converted to underlying const by implicit conversion.

const with reference

You can bind a reference to an const variable called a reference to const, a reference to a constant.

Unlike a regular reference, a reference to a constant cannot be used to modify the object to which it is bound


const int ci=5;
const int &r=ci;
r=6// Errors cannot be modified by constant references 
int &r2=ci// Error, trying to make 1 An unusual reference point 1 A constant object. 

Initialization of the const reference

We know that 1 must be initialized with an object for reference, and that the object's type needs to match it.

An exception to this is const, which allows you to initialize a constant reference with any expression, as long as the result of the expression can be converted to the type of the reference, or even bind a very large number of objects, literals, or expressions to a constant reference.


int i=42;
const int &r1=i;// Allows you to const int& Bound to the 1 An ordinary int On the object 
const int &r2=3.14;// Correct: r2 is 1 10 constant references 
const int &r3=r1*2;// Correct: r3 is 1 10 constant references 
int &r4 =r1*2;// Error, non-scalar references cannot be initialized with an expression 

C++primer gives reasons for doing this:

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. ri is supposed to be an integer operation, but dval is a double floating-point number instead of an integer. So to ensure that ri binds to an integer, the compiler changes the above code into the following:


const int temp=dval;// Generated by a double precision floating point number 1 A temporary integer constant 
const int &ri=temp;// let ri Bind to this temporary quantity 

In this case,ri binds a temporary quantity object. A temp object is an unnamed object created temporarily when the compiler needs a space to hold the evaluation result of an expression. Programmers often refer to temporary quantity objects as temporary quantities for short.

const and auto type specifiers

The auto type specifier is a newly introduced type specifier in C++11 that can automatically infer the type.

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

When deducing objects with const, the compiler 1 generally ignores the top layer const, while the bottom layer const remains. In addition, for references, there is no real entity, so if a reference is used to initialize the auto type, auto is actually the type of object that the reference refers to, not the reference. To indicate that it is a reference type, auto is needed & .


const int ci=i,&cr=ci;
auto b=ci;//b is 1 An integer (ci The top of the const The feature is ignored )
auto c=cr;//c is 1 An integer (cr is ci The alias ,ci Itself is 1 A top const)
auto d=&i;//d is 1 Integer pointer ( The address of an integer is a pointer to an integer )
auto e=&ci;//e is 1 A pointer to an integer constant ( The address of the constant object is 1 Of the underlying const)

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

[

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

]

conclusion


Related articles: