C++ Primer reading notes

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

Keywords: C++

Added by blackwinged on Sat, 29 Jan 2022 07:49:35 +0200