C/C++中const foo**与foo** const声明是否完全相同?
核心结论
首先你最开始的前提判断就是错的:void bar(const foo*)和void bar(foo* const)完全不等价,你提到的两个二级指针声明也同样不等价。
const修饰指针的基本规则
C/C++里判断const修饰对象的规则非常明确:
- const优先修饰它紧挨着的左侧内容
- 如果左侧没有可修饰的内容,才会修饰紧挨着的右侧内容
按这个规则拆解一级指针的两个声明:
const foo*:const左侧无内容,修饰右侧的foo,语义是指向不可变foo的可变指针:不能通过这个指针修改它指向的foo对象的值,但可以修改指针本身存储的地址,让它指向其他foo对象。foo* const:const紧挨着左侧的*(也就是指针本身),语义是指向可变foo的不可变指针:可以通过这个指针修改指向的foo对象的值,但指针本身存储的地址不能修改,永远指向初始化时绑定的对象。
两者语义完全不同,不存在等价关系。
二级指针对比
同样按规则拆解你列的两个二级指针声明,二者语义差异更大:
const foo**:const修饰最内层的foo,语义是指向「指向不可变foo的可变指针」的可变指针:两层指针本身的指向都可以修改,但不能通过这个二级指针链路修改最内层foo对象的值。foo** const:const紧挨着左侧的外层*(也就是二级指针本身),语义是指向「指向可变foo的可变指针」的不可变指针:最外层二级指针本身的指向不能修改,但内层一级指针的指向可以改,最内层foo对象的值也可以通过链路修改。
const前置的写法调整
如果不借助typedef,没有办法在不改变语义的前提下把foo** const里的const挪到声明最前面:
const一旦挪到最开头,左侧没有可修饰内容,就会直接修饰紧邻的foo,语义直接变成const foo**,和原语义完全不符。
如果允许用typedef封装二级指针类型,就可以实现const前置且语义不变:
typedef foo** foo_ptr_ptr; void bar(const foo_ptr_ptr);
此时const foo_ptr_ptr里的const修饰整体的二级指针类型,和foo** const语义完全等价。
内容的提问来源于stack exchange,提问作者P45 Imminent
相关产品推荐
相关产品推荐

