2.4 const qualifier
const modifies a variable whose value cannot be changed
After const object is created, its value cannot be changed, so it must be initialized
1 initialization and const
Const type objects can only perform operations that do not change their contents. For example, use const object to initialize another object (because copying the value of an object will not change it, and the copied new object has nothing to do with the original object)
int i = 42; const int ci = i; //Correct: the value of i is copied to ci int j = ci; //Correct: the value of ci is copied to j
Copying the value of an object does not change it. Once the copy is completed, the new object has nothing to do with the original object.
2 const objects are only valid in files by default
When a const object is defined in initialization mode, the compiler will replace the variable with the corresponding value during compilation
Define const variables for multiple files and avoid repeated definitions of the same variable. Const objects are only valid within files by default. Const variables with the same name in multiple files of the program are equal to independent variables defined in multiple files
If const objects are shared among multiple files, extern must be added before variable definition
// file_l.cc defines and initializes a constant that can be accessed by other files extern const int bufSize = fen(); // file_l.h and file_ l. The bufSize defined in CC is the same extern const int bufSize;
file_l.cc defines and initializes bufSize. Because it is a constant, it needs to be decorated with extern to be used by other files
file_ l. The declaration in h also has extern modification (qualification), which is used to indicate that bufSize is not defined in this document, and its definition is elsewhere
Section 2.4 exercise
[Exercise 2.26] Which of the following sentences are legal? If there are illegal sentences, please explain why? (a) const int buf; // Illegal, initialization required (c) const int sz = ent; // It has nothing to do with const during legal initialization (b) int ent = 0; // legitimate (d) ++cnt; ++sz; // Illegal, const restricted object, its value cannot be modified
2.4.1 reference to const
Binding a reference to a const object is called a reference to a constant, or constant reference for short
Unlike ordinary references, a constant reference cannot modify the object it binds to
const int ci = 1024; const int &rl = ci; //Correct: references and their corresponding objects are constants rl = 42; //Error: rl is a reference to a constant int &r2 = ci; //Error: make non constant reference point to constant object
The non constant reference cannot point to the constant object. Because the initialization is legal, the value of the reference object can be changed through it, which is obviously incorrect
1 initialization and reference to const
With two exceptions, the reference type is the same as the reference object type
The first case: when initializing 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 reference type
int i = 42; //Bind int constant reference to ordinary int object const int &rl = i; const int &r2 = 42; //Correct: rl is a constant reference const int &r3 = rl * 2; //Correct: r3 is a constant reference int &r4 = rl * 2; //Error: r4 is a normal non constant reference
[understand exceptions]
When a constant reference is bound to another type
double dval = 3.14; const int &ri = dval;
In order to ensure that the constant integer reference ri is bound to an integer, the compiler will replace the above code with the following form
//Generates a temporary integer from a double precision floating-point number const int temp = dval; //Let ri bind this temporary quantity const int &ri = temp;
Therefore, ri binds a temporary quantity object. When ri is not a constant and ri is allowed to be assigned, the value of the object referenced by ri will be changed, which is obviously unreasonable
Temporary quantity object: when the compiler needs a space to temporarily store the evaluation result of the expression, an unnamed object is temporarily created. The temporary quantity object is called temporary quantity for short
2 the reference to const may refer to a non const object
Constant reference defines the reference operation and does not limit whether the reference object is a constant
Its object may be an extraordinary quantity, and its value can also be changed in other ways
int i = 42; int &rl = i; //Reference ri binding object i const int &r2 = i; //Modifying the value of i by r2 is not allowed rl = 0; // rl is not a constant, and the value of i is modified to 0 r2 = 0; // Error: r2 is a constant reference
2.4.2 pointer and const
Like references, pointers can point to constants or non constants. Like a constant reference, a pointer to a constant cannot change the value of the object.
To store the address of a constant object, you can only use a pointer to the constant:
const double pi = 3.14; //pi is a constant whose value cannot be changed double *ptr = π //Error: ptr is a normal pointer const double *cptr = π //Correct: cptr can point to a constant *cptr = 42; //Error: cannot assign value to * cptr
With two exceptions, the pointer type must be consistent with the object type it refers to
The first exception: a pointer to a constant points to a non constant object
A pointer to a constant only requires that the value of the object cannot be changed through the pointer, but does not specify that the value of that object cannot be changed by other means
double dval = 3.14; //dval is a double precision floating-point number whose value can be changed cptr = &dval; //Correct: but the value of dval cannot be changed through cptr
1 const pointer
The pointer is an object rather than a reference. Similar to other object types, the pointer itself can be defined as a constant, which is called a constant pointer. The constant pointer must be initialized, and its value (the address stored in the pointer) cannot be changed after initialization
Put an asterisk before the const keyword to indicate that the pointer is a constant. That is, the pointer value remains unchanged, not the point value
int errNumb = 0; int *const curErr = errNumb; // Currerr will always point to errnum const double pi = 3.14159; const double * const pip = π // pip is a constant pointer to a constant object
The effective way to judge the meaning of the declaration is to read from right to left. In this example, the symbol closest to currr is const, indicating that it is a constant object, and the object type is determined by the rest of the declarator
The remaining symbol of the declarator is *, indicating that it is a constant pointer. Finally, the basic data type part of the declaration statement states that the constant pointer points to an int object
Constant pointer, which cannot change the stored address value
A pointer to a constant cannot change the value of the object
Constant pointers to constants, object values, and stored address values cannot be changed
Section 2.4.2 exercise
[Exercise 2.27] Which of the following initializations are legal? Please explain why. (a) int i = -1, &r = 0; //Illegal. The referenced type is an object and 0 is an integer literal (b) int * const p2 = &i2; //Legal constant pointer, cannot modify pointer value (c) const int i = -1, &r = 0; //Legal, initialize constant reference, which can be converted into reference type (d) const int * const p3 = &i2; //Legal, constant pointer to const int constant (e) const int *pl = &i2; //Legal, pointer to const int constant (f) const int &const r2; //Illegal, reference must be initialized (g) const int i2 = i, &r = i; //legitimate [Exercise 2.28] Explain what the following definitions mean and pick out the illegal ones (a) int i, * const cp; //Illegal int integer, constant pointer must be initialized (b) int *pl, *const p2; //Illegal pointer to int integer object (c) const int ic, &r = ic; //Legal constant, integer, constant reference (d) const int *const p3; //Illegal. A constant pointer to a constant integer must be initialized (e) const int *p; //Legal pointer to constant [Xi 2.29] Suppose you have variables defined in the previous exercise,Which of the following statements are legal? Please explain why (a) i = ic; //Legal assignment of constant integer to integer (b) pl = p3; //Assign a legal constant pointer to a constant integer to a pointer (c) pl = ⁣ //Illegal. Must be a pointer to a constant (d) p3 = ⁣ //Legal constant pointer to constant integer (e) p2 = pl; //Legal assignment of constant pointer with pointer (f) ic = *p3; //legitimate
2.4.3 top const
Whether the pointer itself is a constant or not and whether the object referred to by the pointer is a constant are two independent questions. Use const at the top of the noun to indicate that the pointer is a constant, and const at the bottom of the noun to indicate that the object is a constant
The top-level const can indicate that any object (applicable to any data type) is a constant, such as arithmetic type, class, pointer, etc. The bottom const is related to the basic types of composite types such as pointers and references. The pointer type is special, which can be either the top const or the bottom const
int i = 0; int * const pl = &i; // The value of pl cannot be changed. This is a top level const const int ci = 42; // The value of ci cannot be changed. This is a top level const const int *p2 = &ci; // It is allowed to change the value of p2, which is an underlying const const int *const p3 = p2; // Both top and bottom const const int &r = ci; // Consts used to declare references are the underlying const s
When copying objects, the top-level const differs from the bottom-level const
The top-level const is not affected because the copy operation does not change the value of the copied object
Underlying const: the copy in and copy out objects must have the same underlying const qualification, or the data types of the two objects must be convertible
int *p = p3; // Error: p3 contains the underlying const definition, but p does not p2 = p3; // Correct: p2 and p3 are the underlying const p2 = &i; // Correct: int * can be converted to const int* int &r = ci; // Error: normal int & cannot be bound to int constant const int &r2 = i; // Correct: const int & can be bound to an ordinary int
Conclusion: non constant quantity can be converted into constant, and vice versa
Section 2.4.3 exercise
[Exercise 2.30] For the following statements,Please specify that the object is declared as the top level const Or the bottom const? const int v2 = 0; // bottom int vl = v2; // Non const int *pl = &vl, &rl = vl; // Non const const int *p2 = &v2, *const p3 = &i, &r2 = v2; // Bottom, top, bottom, top [Exercise 2.31] Suppose you have the statements you made in the previous exercise,Which of the following statements are legal? Please specify the top level const And the bottom const What is reflected in each example rl = v2; // Illegal assignment object is the underlying const pl = p2; // Illegal constant cannot be converted to non constant p2 = pl; // Legal variables can be converted into constants pl = p3; // Illegal constant cannot be converted to non constant p2 = p3; // legitimate
2.4.4 constexpr and constant expressions
Constant expression refers to the expression whose value will not change and the calculation result can be obtained during compilation. const object initialized with constant expression is also a constant expression
Whether an object (or expression) is a constant expression depends on its data type and initial value
const int max_files = 20; // max_files is a constant expression const int limit = max_files + 1; // limit is a constant expression int staff_size = 27; // staff_size is not a constant expression const int sz = get_size(); // sz is not a constant expression staff_size The initial value of is a literal constant, but its data type is int sz Is a constant, but its value can only be obtained at runtime, and it is not a constant expression
constexpr variable
In complex programs, it is difficult to distinguish whether an initial value is a constant expression. The new C++11 standard allows variables to be declared as constexpr type, so that the compiler can verify whether the variable value is a constant expression
Variables declared as constexpr must be constants and must be initialized with constant expressions
constexpr int mf = 20; // 20 is a constant expression constexpr int limit = mf + 1; // mf + 1 is a constant expression constexpr int sz = size(); // When size is a constexpr function //Is the correct statement
Although ordinary functions cannot be used as the initial value of constexpr variables, the new standard allows the definition of a constexpr function. So that the result can be calculated at compile time, so that the function can be used to initialize the constexpr variable
Suggestion: if the variable is a constant expression, declare it as constexpr type
Literal type
The value of a constant expression needs to be evaluated at compile time, so there are restrictions on the type when constexpr is declared
Because these types are relatively simple and the value is obvious, they are called literal types. Arithmetic types, references, and pointers are literal types, while custom classes, I / O libraries, and string types are not
The initial value of a constexpr pointer must be nullptr or 0, or an object stored in a fixed address
The variables defined in the function body are generally not stored in the fixed address, but the address of the object defined outside the function remains unchanged
It will also be mentioned in section 6.1.1 that a function is allowed to define a class of variables whose valid range is beyond the function itself. Such variables also have fixed addresses like variables defined outside the function body
Pointer and constexpr
If a pointer is defined in the constexpr declaration, the qualifier constexpr is only valid for the pointer and has nothing to do with the object to which the pointer refers
const int *p = nullptr; // p is a pointer to an integer constant constexpr int *q = nullptr; // q is a constant pointer to an integer
Section 2.4.4 exercise
[Exercise 2.32] Is the following code legal? If illegal,Please try to correct it int null = 0, *p = null; wrongful int x = 0; null Is keyword constexpr int *p = nullptr; Cannot assign an integer to a pointer
Variables have fixed addresses as well
Pointer and constexpr
If a pointer is defined in the constexpr declaration, the qualifier constexpr is only valid for the pointer and has nothing to do with the object to which the pointer refers
const int *p = nullptr; // p is a pointer to an integer constant constexpr int *q = nullptr; // q is a constant pointer to an integer
Section 2.4.4 exercise
[Exercise 2.32] Is the following code legal? If illegal,Please try to correct it int null = 0, *p = null; wrongful int x = 0; null Is keyword constexpr int *p = nullptr; Cannot assign an integer to a pointer