const / define / static / extern
2015-11-12 本文已影响601人
iOS_成才录
一、全局变量 / 宏 / 常量 比较
- 全局变量:
int age = 20; 缺点:能修改,优点:内存中只保存一份,不会产生很多临时空间
+ 宏:
```objc
#define age 20 优点:不可修改,缺点:会产生很多临时的内存空间
- 常量:
const int age = 20;优点:不能修改只读,且内存中只会有一份存储空间
// 等价于 int const age = 20;
-
注意:
Snip20150906_60.png
Snip20150906_61.png
Snip20150906_62.png
二、 总结:
-
const:const只修饰它右边的内容,被const修饰的内容都是常量。
-
static:
- 被static修饰的全局变量/常量,仅限当前文件访问
- 被static修饰的局部变量,只会占用一块内存,整个程序运行不会销毁,只会初始化一次。
-
extern:可以引用一个全局变量/常量
-
常量使用潜规则
常量必须在编译时就必须有确定的值
三、作用域
- int money; 全局变量:
- 默认情况下,全世界都是可以访问的,不仅限某一个类,利用extern可以引用一个全局变量,如:extern int money; =>引用某个类的全局变量money。而且我们可以对全局变量money进行修改。
-
const int money ;
-
默认情况下,全世界都可以用,但是不可用改,只读:extern const int money; =》 只读不可改。
-
注意:类中函数也是:全世界都可以访问的,我们只需要引用即可调用。引用函数写法:extern void eat();
-
-
static int money;
- 被static修饰的全局变量:作用域:只限制在当前文件中访问使用。
-
static int const money;
- 被static修饰的全局常量:仅限当前文件中使用,且不可改,只读
四、 应用:
1. 字符串常量
// cellID 字符串被const 修饰了,,字符串类型的cellID不可改
NSString * const cellID = @"cellTagID"; // 注意:NSString字符串 == 一个指针指向它
int const *age = 10; // age 不可修改
-
总结写法:const 和 变量 紧挨着避免不必要的错误
-
常量使用潜规则
常量必须在编译时就必须有确定的值
// 是错误的,因为[UIColor redColor] -> 是在运行时才确定的,不符合常量使用的潜规则
UIColor *const JPGlobalColor = [UIColor redColor];
// 宏定义正确
#define JPGlobalColor [UIColor redColor]
2. cell标识
// JPHomeCellID,仅限当前文件,不可改,只占一份内存空间。
static NSString *const JPHomeCellID = @"JPHomeCellID";
3. URL字符串,保证全世界内存只有一份且全世界都可以访问,且不可更改
3.1 思路分析
- 全世界都可以访问:所有不能用static(仅限某一个类访问)
- 全世界内存都只有一块:不能用#define宏(多次拷贝,会存在多块内存)定义;
- 不可更改:定义为
常量
3.2 解决方案
- 方案一(不可行):定义常量放入pch文件 : 缺点-> 所有的类引用,重复定义
// 不可行,因为pch文件内容会拷贝到每一个文件中,这样会引起重复定义问题
NSString *const JPRequestURL = @"http://baidu.com";
- 方案二(不可取):麻烦
- 1.常量的定义放在一个const.m文件中
NSString *const JPRequestURL = @"http://baidu.com";
- 2.然后在pch文件中引用const.m文件中定义的常量
```objc
extern NSString *const JPRequestURL; // extern 引用常量,这样就解决的只在pch中定义常量引起的重复定义的问题,而且保证了一份内存
- 3.缺点:如果有100个,就需要在const.m文件中定义100个常量,然后在pch文件中利用extern引用100个定义的常量
- 方案三(最终方案):
- 简单,解决了方案二中引用麻烦的问题
- 步骤:
- 在const.m(定义所有常量)中定义常量的值,
NSString *const JPRequestURL = @"http://baidu.com";
+ 在const.h文件(引用定义的全局常量)中引用定义的全局常量
```objc
#import <UIKit/UIKit.h>
// URL
UIKIT_EXTERN NSString *const JPRequestURL;
+ 在pch文件中导入const.h文件即可
#import "const.h"
4. 定义Rect结构体变量commonRect,要求只有本文件中能访问,且不可修改
-
使用全局处理,取代宏定义
-
思路分析:只有本文件中能访问 -> static修改commonRect变量;不可修改 -> 且还用const修改;
-
注意:Rect结构体创建有两张方式 : CGRectMake(0,0,50,50) ->运行时才能确定其值;{{0,0},{50,50}} ->编译时就确定其值了。如何选择呢?
- 很明显,我们需要定义常量,还记得常量的潜规则是什么吗?-> 常量的值必须编译时就确定,否则会报错的,所以我们只能通过{{0,0},{50,50}}方式创建结构体常量。
-
实现
// 正确
static CGRect const commonRect = {{0,0},{50,50}};
// 错误
static CGRect const commonRect = CGRectMake(0,0,50,50);
五、全局常量写法
1. 仅限本文件中访问
- 在.m中写下面代码
static 类型 const 常量名 = 常量值;
2. 全世界都要访问
- 1>在const.m文件中,(const.m定义所有全局常量)
#import <UIKit/UIKit.h>
类型 const 常量名 = 常量值;
.........
- 2>在const.m文件中,写下列代码(引用所有全局常量)
#import <UIKit/UIKit.h>
UIKIT_EXTERN 类型 const 常量名;
.........
- 3>在pch文件中包含const.m文件,导入头文件
#import "const.h"