回顾:普通(非常量)指针
对于普通(non-const)指针,我们既能改变它指向的地址(通过给指针赋新地址),也能改变所指地址上的值(通过对解引用后的指针赋值):
int main() {
    int x{ 5 };
    int* ptr{ &x }; // ptr 为普通指针
    int y{ 6 };
    ptr = &y;   // 改变指向
    *ptr = 7;   // 改变值
}
指向 const 对象
若目标对象被声明为 const,则不能让普通指针指向它:
int main() {
    const int x{ 5 };
    int* ptr{ &x }; // 编译错误:无法将 const int* 转换为 int*
}
道理显而易见:普通指针解引用后可修改值,这会破坏对象的常量性。
“指向 const 的指针”(pointer to const)
在类型前加 const,声明一个指向 const 值的指针:
int main() {
    const int x{ 5 };
    const int* ptr{ &x }; // OK:指向 const int
    *ptr = 6;             // 错误:不能通过 ptr 修改 const 值
}
注意:指针本身不是常量,因此仍可改变它指向的地址:
const int x{ 5 }, y{ 6 };
const int* ptr{ &x };
ptr = &y; // OK:指向新的 const int
指向 const 的指针同样可指向非 const 变量,只是通过该指针访问时把对象视为 const:
int x{ 5 };
const int* ptr{ &x }; // OK
*ptr = 6;    // 错误:不能通过 ptr 修改
x = 6;       // OK:直接修改原变量
const 指针
若希望指针本身在初始化后不可再指向别处,应在 * 后加 const:
int main() {
    int x{ 5 }, y{ 6 };
    int* const ptr{ &x }; // const 指针,指向 int
    ptr = &y; // 错误:地址不可再改
    *ptr = 7; // OK:可修改所指对象
}
“指向 const 的 const 指针”
在类型前和 * 后都加 const 即可得到既不能改指向、也不能改值的指针:
int value{ 5 };
const int* const ptr{ &value }; // 指向 const int 的 const 指针
四种组合速记
只需记住 4 条规则,逻辑清晰:
- 普通指针 - int* ptr- 可改指向
- 可改值
- 不能指向 const 值
 
- 指向 const 的指针 - const int* ptr- 可改指向
- 不能改值
- 可指向 const 或非 const 对象
 
- const 指针 - int* const ptr- 不能改指向
- 可改值
 
- 指向 const 的 const 指针 - const int* const ptr- 不能改指向
- 不能改值
 
声明速记
- const在- *左侧:修饰所指值
- const在- *右侧:修饰指针本身
示例:
int v{ 5 };
int* ptr0{ &v };               // 普通指针
const int* ptr1{ &v };         // 指向 const int
int* const ptr2{ &v };         // const 指针
const int* const ptr3{ &v };   // 指向 const int 的 const 指针
