前言
- 记得刚学
ObjC
的时候,总是被顶层const
和底层const
搞的头晕晕的(也可能是我本人比较笨的原因吧:])。谨以此文,记录我踏过的坑,同时也希望为后人扫个雷
先谈C++ 顶层const与底层const
最早了解到
const
相关的话题时,是在阅读C++ Primer一书时,里面提到的两个概念顶层const:表示指针本身是个常量
底层const:表示指针所指的对象是一个常量
在C++中,由顶层
const
与底层const
+ 指针类型,又衍生了两个概念- 常量指针:顶层
const
指针,即指针不可变,不能再指向其他元素,但指针指向的元素自身可变 - 指针常量:底层
const
指针,即指针可变,但指针指向的元素自身不可变
- 常量指针:顶层
概念本身是很简单的,但是上了代码之后,我们能认清下面哪个是顶层,哪个是底层吗?
|
|
图解
- 图解标注
- 空心箭头表示指向的对象值可变 <=> 实心箭头表示指向的对象值不可变
- 虚线表示指向对象这种关系可变 <=> 实心箭头表示指向对象这种关系固定了
- 图解标注
小总结
- 指针与
const
const
靠近指针符号- =>
const
为顶层const
,指针为常量指针,指向关系不能变
- =>
- const两边在中间或靠近数据类型
- =>
const
为底层const
,指针为指针常量,指向关系可变,指向元素不可变
- =>
- 引用与
const
- 引用变量:因为引用不能二次赋值,所以只能声明底层
const
- 引用变量:因为引用不能二次赋值,所以只能声明底层
- 指针与
再谈ObjC const
const
在ObjC
中的用途代替
#define
声明常量,保证编译器有类型检测(见下图)12const NSString *const kGoodbyeString = @"Goodbye";我们希望能够保证
kGoodbyeString
不被修改,如果我们不去考虑底层const
/顶层const
的问题,我们可以直接使用两个const
来让他达到和#define
一样的效果,但这样其实在使用某些API
时,会出现warning
,因此我并不建议直接使用两个const
讨论
ObjC
与C++
的const
用法是否一样?很幸运,是的。下述三种const
用法均与C++
的用法一样1234int a = 1;const int *ptrA = &a;int const *ptrB = &a;int *const ptrC = &a;那我们要讨论的是什么呢?我们要讨论的是,当指针遇上对象,我们究竟需要什么样的
const
来达到#define
的效果图解 - 开始
- 图解标注
- 在ObjC中,我们把@”xx”称作字符串常量,在ObjC中,实际上有一个字符串常量池,我们可以把它看作一个集合。用到的字符串都会出现在这里,且只出现一次。然后指针指向这块内存,以降低内存消耗。所以,我们代码中的
constStringA
、constStringB
、constStringC
实际上都是指向了这块内存。其中,constStringA
、constStringB
是指针常量,constStringC
是常量指针 - 空心箭头表示指向的对象值可变 <=> 实心箭头表示指向的对象值不可变
- 虚线表示指向对象这种关系可变 <=> 实心箭头表示指向对象这种关系固定了
- 在ObjC中,我们把@”xx”称作字符串常量,在ObjC中,实际上有一个字符串常量池,我们可以把它看作一个集合。用到的字符串都会出现在这里,且只出现一次。然后指针指向这块内存,以降低内存消耗。所以,我们代码中的
- 图解标注
接下来,我们来执行一段代码,再来看看状态
1234constStringA = @"a";constStringB = @"b";// ==== Error Code ====// constStringC = @"a";图解 - 执行代码后
- 图解标注
- 执行代码后,实际上改变的是指针的指向,而非内存里字符串常量的值
- 空心箭头表示指向的对象值可变 <=> 实心箭头表示指向的对象值不可变
- 虚线表示指向对象这种关系可变 <=> 实心箭头表示指向对象这种关系固定了
- 从图上看,我们可以知道,对于字符串常量对象而言,因为字符串本身就不可变了,我们希望指向他的指针的指向关系不能改变。所以我们需要使用的应该是常量指针(
constStringC
)
- 图解标注
上述部分只是针对字符串常量对象而言,针对字符串常量,我们如果想要达到
#define
的效果,需要使用的应该是常量指针(即顶层const
)由于在
ObjC
中,大部分对象都会涉及到指针,所以对于对象而言,我们首先要使用顶层const
。其次我们还要研究对象本身是否可变,如果本身可变,则要用底层const
小总结
- 对于一般的字符串而言,我们应该使用的是顶层
const
- 如果不想使用两个
const
,我们则需研究对象本身是否可变,如果本身可变,则要用底层const
+ 顶层const
;否则用一个顶层const
即可
- 对于一般的字符串而言,我们应该使用的是顶层
- 本文代码下载
- Github Repo - CppLearningConst
- Github Repo - ObjCLearningConst
- 运行环境:Xcode 8.1(8B62)
- Last Edited:2016.12.5
- Author:@Seahub
- Please contact me if you want to share this Article, 3Q~