Overview
1.普通指针和 const 之间的天然冲突
2.Pointer to const value 指向const值的指针
3.Const pointers const指针
4.指针相关的 const 修饰总结
普通指针和 const 之间的天然冲突
1.对于一个普通的指针, 我们可以修改指针指向的地址或者修改指针指向的值
int main() {
int x{5};
int* ptr{&x}; // ptr is a normal (non-const) pointer
int y{6};
ptr = &y; // we can point at another value
*ptr = 7; // we can change the value at the address being held
return 0;
}
2.但是我们想一个指针指向一个 const 值的时候, 普通的 (非const) 指针就无效了; 仔细思考下这种设定是 make sense 的, 因为 const 的值就是不能修改的. 如果直接一个指针能直接指向, 那么就能通过 *p = 4 这种类似的操作修改这个值了, 违反了原有变量本身 const 的设定
int main() {
const int x{5}; // x 是一个 const 值
int* ptr{&x}; // 编译报错: "const int *" 类型的值不能用于初始化 "int *" 类型的实体C/C++(144)
return 0;
}
Pointer to const value 指向 const 值的指针
1.这里我们的研究是 const value 的相关操作, 具体来说是要在研究的是指向 const value 的指针应该如何被正确定义
2.这种指向 const value 的指针称之为 pointer to const value, 指向 const value 的指针
3.定义pointer to const value的方式是在 int 类型前面增加 const, 定义为 const int ptr
4.我们唯一要理解的概念是 const 这里是作为一个修饰符出现, 给这种指针赋予了一个新的属性, 这个新属性就是也就是这个指针指向的 value 再也不能被修改, 无论修饰的是 const value 还是非const value
const int x = 5;
const int* p = &x;
5.pointer to const value 的存在, 解决了非 const 的指针直接指向 const 值的造成的语义不合理没法编译通过的问题, 使得我们可以很合法地对 const value 进行指针使用
6.这里需要声明的是: const 放在int 的左边是修饰的是被指向的 const value, 因此对这个指针指向的值的赋值操作将不再合法
7.这里需要声明的是: const 放在int 的左边是修饰的是被指向的 const value, 但是这个指针可以重新指向新的 const 的值
int main() {
const int x{5};
const int* ptr{&x}; // int* 前面增加 const修饰, 这样就声明一个指向 const 的指针, 这样ptr就是一个指向 const int的 (且合法编译可通过的) 指针;
*ptr = 6; // 不允许的操作: 因为是指向 const 值的指针, 所以不能仅仅通过 *ptr = 6 的操作而进行赋值操作;
const int y{6};
ptr = &y; // 允许的操作: const int* 定义的ptr可以指向y, ptr只需要可以指向一个常量就可以, ptr可以指向任意另一个 const value;
return 0;
}
8.这时候我们想想 const int ptr 指向一个非const的变量 x, 会发生什么?
我们定义了 const int ptr, 这里const修饰的主体没有发生变化, 仍然是指向一个不可修改值的指针, 无论修饰的是const value 还是 non-const value, 都是一样不可修改的
int main() {
int x{5}; // non-const
const int* ptr{&x}; // ptr points to a "const int"
*ptr = 6; // 不允许, 指针ptr指向的是const int 类型的值, 所以是不能改值的;
x = 6; // 允许, 指向const类型的值的指针能修改值, 但是作为non-const的变量, 还是可以直接修改值的
return 0;
}
Const pointers const指针
1.与 pointer to const value 不同, 还有一种情况是我们需要让指针 (也就是保存的地址) 变得不可变, const pointer 就是这样的一种 pointer, 这种指针的const是修饰在指针保存的地址本身, 指针一旦初始化了保存的地址, 那么这个指针不再能变
2.如果要设定指针保存的地址不能变, 我们要加在 int 的后面加一个 const, 也就是说 const 修饰符出现在 的右侧
int* const ptr;
3.const 指针因为一旦初始化就不能改变了, 所以它的初始化其实就是它的唯一化
int main() {
int x{5};
int y{6};
int* const ptr{&x}; // const指针可以初始化为ptr
ptr = &y; // 一旦初始化, 指针保存的地址不能被改变了, 因为地址已经绑定在x上, 地址的内容没有改变
// vscode报错提示: 表达式必须是可修改的左值C/C++(137)
return 0;
}
4.const 可以修饰指针保存的地址, const 也可以修饰地址保存的内容, 那么可以双剑合璧一下, 让指针保存的地址和指针地址指向的内容都不可修改, 也就是 const 指针指向 const value; 在这种情况下, 这种指针通过 dereference 值也不能改, 指向的地址也不能改
int main() {
int value = 5;
// 想清楚这2个const分别起到什么作用
// int* 左边的 const 是修饰 const 的值不能变, 值无法通过 dereference
// int* 右边的 const 是修饰 ptr 的地址不能变, ptr 一旦定下来地址, 那么就不能再改地址了
const int* const ptr = &value;
return 0
}
指针相关的 const 修饰总结
指向相关的操作, 其实只有 4 个规则, 现在总结如下:
A non-const pointer can be assigned another address to change what it is pointing at.
A const pointer always points to the same address, and this address can not be changed.
A pointer to a non-const value can change the value it is pointing to. These can not point to a const value.
A pointer to a const value treats the value as const when accessed through the pointer, and thus can not change the value it is pointing to. These can be pointed to const or non-const l-values (but not r-values, which don’t have an address).
intuitively,
1.const 指针这玩意讲出来感觉有点绕口令的感觉, 但其实每一种有确定的逻辑且没有任何的歧义, 只需要抓住, const 是修饰谁的就能确定应该是怎样的, 指针无非是一个地址和一个值, const 要么修饰地址, 要么修饰值, 要么就是二者都修饰
2.一个 (只要) 非 const 的指针, 可以随意重新分配另一个地址, 也就是指针任意指向谁都行
3.一个 const 指针, (区别于 pointer to const value), 只能指向一个固定的地址, 一旦固定了地址, 再也不能指向其他的地址
4.一个指向 非 const value 的指针. 指针指向的值随意修改, 因为指向的是非 const
5.一个指向 const value 的指针. 这种指针被固定下来的身份是指向 const valued
Reference
1.https://www.learncpp.com/cpp-tutorial/introduction-to-pointers/.
转载请注明来源, from goldandrabbit.github.io