2.4 const qualifiers
The keyword const adds a limit to the type of the variable
const int bufSize = 12;
The object modified by const cannot change its value once it is created, so the object modified by it must be initialized.
Compared with non-const type objects, objects modified by const can perform most of the operations of non-const objects, but cannot be modified or reassigned.
By default, const objects are only available in files
When a const-modified variable is initialized at compile time, the compiler will change all places where the variable is used into the corresponding value during compilation.
("C++ Primer")
2.4.1 Reference constants
A reference constant cannot modify the object it is bound to, and a non-const reference cannot point to a constant object
int i = 10;
const int &r = i;
r = 11; // 错误:表达式必须是可修改的左值
const int i = 10;
int &r = i; //错误:将 "int &" 类型的引用绑定到 "const int" 类型的初始值设定项时,限定符被丢弃
initialization and reference to const
The type of the reference must be consistent with the type of the referenced object. Exception: Any
expression is allowed to be used as the initial value when initializing a constant reference, as long as the result of the expression can be converted to the reference type.
int i = 10;
const int &r = i; // 允许常量引用绑定到一个普通int对象上
const int &r1 = 45; // 正确:r1是一个常量引用
const int &r2 = r*2; // 正确:r2是一个常量引用
int &r3 = r1*2; // 错误:r3是一个普通的非常常量引用
A reference to const may refer to an object that is not const
A constant reference only limits the operations that the reference can participate in, and does not limit whether the referenced object itself is a constant. Since an object may also be a non-const, other means of changing the value of a constant reference are allowed.
int i = 10;
const int &r = i;
i = 15;
cout << r << endl; // 15
int &r1 = i;
r1 = 16;
cout << r << endl; // 16
2.4.2 const and pointers
Pointers can point to constants or non-constants. To store the address of a constant object, the pointer must be modified by the const keyword. A pointer to a constant cannot be used to change the value of the object it points to.
const double i = 3.14; // 常量对象
const double *p = &i; // 正确:p是指向常量的指针
*p = 12; // 错误:指向常量的指针不能用于改变其指向的对象的值
double *p1 = &i; //错误:"const double *" 类型的值不能用于初始化 "double *" 类型的实体
The type of a pointer to a constant must be the same as the type of the pointed object, exception:
a pointer to a constant points to a non-constant object
int i = 10;
const int *p = &i; // 正确:常量指针指向了非常量对象
i = 15; // 可以通过修改非常量对象的值来修改指向常量的指针
cout<< *p << endl; // 15
const pointer
Pointers are objects and references are not, so just like other types of objects, it is allowed to position the pointer itself as a constant. The constant pointer (const pointer) must be initialized. Once the initialization is completed, the value of the pointer (the stored address) cannot be changed.
const int i = 10;
const int *const pip = &i; // pip是一个指向常量的常量指针
int i = 15;
int *const p = &i;
cout << *p << endl;//15
*p = 45;
cout << *p << endl;//45
i = 10;
cout << *p <<endl;//10
int k = 33;
p = &k; // 错误:常量指针所存放的地址不可以被改变
The pointer to the constant object must be a pointer modified by const. The pointer to the constant can store the address of the non-constant object or the constant object, and the address stored by the const pointer is fixed.
2.4.3 Top-level const
The pointer itself is an object. Whether the pointer itself is a constant and whether the object pointed to by the pointer is a constant are two independent issues. In order to distinguish these two terms, use the top-level const and the bottom-level const to distinguish.
type | top-level const | underlying const |
---|---|---|
explain | pointers are constant objects | pointer to a constant object |
example | int *const p = &i; | int const i = 10;const int *p =&i; |
Expand the definition of top-level const and bottom-level const: top-level const refers to any constant object, while bottom-level const is related to the basic types of composite types such as pointers and references.
int i = 10;
int *const p1 = &i;// 不可以修改p1的值,这是一个顶层const
const int *p2 = &i; // 可以修改p2的值,这是一个底层const
const int ci = 12;// 不可以修改ci的值,这是一个顶层const
When performing copy operations, there is a clear distinction between top-level const and bottom-level const. The top-level const is not affected, because the object modified by the top-level const is a constant object and cannot be modified. Performing a copy operation will not change the value of the copied object, so whether the object copied in or copied out is a constant does not matter.
int i = 11;
const int ci = 10;
const int *p1 = &ci; // p1:底层cosnt
const int *const p2 = p2; // 第一个const是底层const,第二个是顶层const
i= ci; // 正确:拷贝ci的值,ci是一个顶层const对此操作无影响
p1 = p2; // 正确:p2和p3指向的对象类型相同,p3顶层const的部分不影响
For underlying const, objects copied in and copied out must have the same underlying qualification
const int ci = 10;
const int *p2 = &i;
int *p = p2; // 错误:p2是底层const,而p无底层const资格
2.4.4 constexpr and constant expressions
A constant expression is an expression whose value does not change and whose result can be obtained during compilation. Literal values are constant expressions, and const objects initialized with constant expressions are also constant expressions. Whether an object or expression is a constant expression is determined by its data type and initial value.
const int i = 10;// i是常量表达式
const int l = i +1; // l是常量表达式
int s = 2;// s不是常量表达式,其数据类型只是一个普通的int
const int k = get_size();// k不是常量表达式,因为常量k的初始值是要运行函数之后才能够获取到
constexpr variable
The new C++11 standard stipulates that variables are allowed to be declared as constexpr types so that the compiler can verify whether the value of the variable is a constant expression. A variable declared as cosntexpr must be a constant and must be initialized with a constant expression.
constexpr int i = 20; // 20是常量表达式
constexpr int l = size(); // 当size函数是一个cosntexpr函数时才是一条正确的语句
constexpr variable
The type used when declaring constexpr becomes a "literal value type". Arithmetic types, reference types, and pointers all belong to literal value types, and custom classes, IO libraries, and string types do not belong to literal value types.
The initial value of a constexpr pointer must be nullptr or 0, or an object stored at a fixed address.
Variables in the function body are generally not stored in fixed addresses, so constexpr pointers cannot point to such variables, and the fixed addresses of objects defined in all function bodies can be used to initialize constexpr.
constexpr and pointers
If a pointer is defined in a constexpr declaration, the qualifier constexpr is only valid for the pointer and has nothing to do with the object pointed to by the pointer
const int *p = nullptr; // p是一个指向整型常量的指针
constexpr int *q = nullptr; //q是一个指向整数的常量指针
constexpr sets the defined object q to the top level.