美文网首页iOS学习iOS归纳比较
const / define / static / extern

const / define / static / extern

作者: iOS_成才录 | 来源:发表于2015-11-12 19:50 被阅读601次

    一、全局变量 / 宏 / 常量 比较

    • 全局变量:

    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"
    

    相关文章

      网友评论

      • 鬼丶白:你好 你写的 3. URL字符串,保证全世界内存只有一份且全世界都可以访问,且不可更改。
        这一条我把NSString *const JPRequestURL = @"http://baidu.com&quot;;写到OC 的HeaderFile.h里面 然后把#import "HeaderFile.h"写到pch里面不行吗?
        iOS_成才录:@soime #define是宏定义,重点不是定义在哪,常量定义是常量,而是它们之间的差别和各自使用场景
        鬼丶白:@iOS_成才录 那么使用#define 定义的写在.h 里面还是.m 里面啊
        iOS_成才录:@soime 你写的不对可能,.h文件,把类定义与实现自动生成的代码都删除 ,.h与.m中头只添加#import <UIKit/UIKit.h>,然后按照我上面实现定义与引用
      • 437aff410919:你好,作者。对于这句话“被static修饰的全局变量:作用域:只限制在当前文件中访问使用。”,这里我有一个疑问。
        只限制在当前文件中访问使用,我对此不太理解,我可以在.h文件声明一个static修饰的全局变量。然后在其他文件声明一下这个头文件,然后使用这个static变量。因为在文章里面没看到有人提到过在.h那里声明这个static变量,所以这样做会有什么问题吗?这样算不算可以不在当前文件中访问使用?虚心求解... :flushed:
        437aff410919:@iOS_成才录 谢谢,明白了。
        iOS_成才录:@Tosaka乐园 按照面向对象思想,定义的属性 是 属于类的对象,而static 是 不可以修饰属性可以这么说,当前 你 可以在 @interface上面定义 static 变量,那就不算是 某个类所有吧,是全局的变量, 我上面说的只是在 .m中定义 变量,不知道你说的我理解了没。
      • MonsterNanny:理清了 thx~

      本文标题:const / define / static / extern

      本文链接:https://www.haomeiwen.com/subject/acmxhttx.html