const static extern关键字作用和对比
const
const修饰的为常量,在程序中,常量的值是固定的不能改变的。const有以下两个作用:
- const用来修饰右边的基本变量或指针变量
- 被const修饰的变量就变为只读readonly,不能被修改
比如声明一个值为1的常量a,然后尝试对这个常量a的值做修改:
// a 是一个常量
int const a = 1;
下面代码会报错:Cannot assign to variable 'a' with const-qualified type 'const int'
a = 20;
需要注意的是const能修饰基本变量和指针变量。需要注意他们的区别
int const p; // 是基本变量 const修饰之后 p变为readonly
int const *p; // *p为指针遍历, const修饰之后, *p变为readonly
int *const p; // p为基本变量 const修饰之后 p变为readonly
const的使用
定义一个全局常量,比如有时候使用宏定义
#define
#define APPKEY = @"appeky";
也可以使用const定义一个全局常量
NSString *const appKey = @"appeky";
static
static修饰局部变量
使用static修饰局部变量能够保证局部变量只初始化一次,也就是程序在运行过程中永远只有一份内存,相当于生命周期是整个程序的生命周期。通常在单例中比较常见:
+(Person *)sharedManager {
static dispatch_once_t onceToken; // static修饰局部变量, 保证只初始化一次
dispatch_once(&onceToken, ^{
_sharedManager = [[self alloc] init];
});
return _sharedManager;
}
接下来看一下使用static修饰的局部变量和不使用static修饰的局不变的区别:
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
int idx = 0;
NSLog(@"idx = %d", idx++);
}
每次点击屏幕之后,打印出的idx都是0,那是当第一次进来touchesBegan:withEvent:,先声明一个int型的值为0的idx局部变量,当方法运行完之后这个局部变量的生命周期也就结束了。下一次进来这个方法的时候就重新初始化。
2018-08-08 11:02:05.441311+0800 iOSTest[14608:2029602] idx = 0
2018-08-08 11:02:05.836638+0800 iOSTest[14608:2029602] idx = 0
2018-08-08 11:02:06.859228+0800 iOSTest[14608:2029602] idx = 0
2018-08-08 11:02:07.243072+0800 iOSTest[14608:2029602] idx = 0
2018-08-08 11:02:07.444190+0800 iOSTest[14608:2029602] idx = 0
2018-08-08 11:02:07.601846+0800 iOSTest[14608:2029602] idx = 0
现在给idx加上static修饰,运行之后会有如下打印结果,那是因为static修饰之后idx变成了一个静态的局部变量,即是touch方法走完了,它的生命周期仍然没有结束。下次进来的时候就不需要重新初始化,保证了只初始化一次。
static int idx = 0;
2018-08-08 11:03:31.436579+0800 iOSTest[14632:2034568] idx = 0
2018-08-08 11:03:32.147773+0800 iOSTest[14632:2034568] idx = 1
2018-08-08 11:03:32.563940+0800 iOSTest[14632:2034568] idx = 2
2018-08-08 11:03:32.845052+0800 iOSTest[14632:2034568] idx = 3
2018-08-08 11:03:33.216545+0800 iOSTest[14632:2034568] idx = 4
static修饰全局变量
使用static修饰全局变量能够使全局变量的作用域仅限于当前文件内部,即当前文件内部才能访问该全局变量。
首先肯定有疑惑,某个文件的全局变量,在另外一个文件中能够访问么?
关于这个问题,我们在两个不同的文件中写两个相同的全局变量:
在新建的继承自NSObject的Person.m文件中:
#import "Person.h"
NSUInteger age; // 全局变量
@implementation Person
@end
让后在ViewController中同样声明age全局变量,尝试是否能访问到Person中的age,发现并不能。
image
删去这句代码之后运行,发现报错
image
综上结果:实际上在一个文件中的全局变量在工程的其他文件也是能访问的。如果想要限定只在当前文件访问,可以使用static修饰。
static NSUInteger age;
通常,也是在以GCD创建的单利中使用的比较多
@implementation Person
// static修饰全局变量,让外界文件无法访问
static Person *_sharedManager = nil;
+(Person *)sharedManager {
static dispatch_once_t onceToken; // static修饰局部变量, 保证只初始化一次
dispatch_once(&onceToken, ^{
_sharedManager = [[self alloc] init];
});
return _sharedManager;
}
@end
static修饰函数
这个在ios中用的比较少,多见与C++中。
extern
extern的作用是声明外部全局变量,这个和static正好相反。
比如在一个工程中,很多文件可能都需要使用同一个变量,比如网络请求的基地址等,就可以放在一个单独的文件中,使用欧冠extern关键字声明为外部全局变量。
需要注意的是extern只能声明,不能用于实现
.h
extern NSString *const baseUrl;
.m
NSString *const baseUrl = @"https://www.xxx/";