代码之家  ›  专栏  ›  技术社区  ›  mahboudz

何时使用静态字符串与定义

  •  45
  • mahboudz  · 技术社区  · 15 年前

    我有点困惑什么时候最好用:

    static NSString *AppQuitGracefullyKey = @"AppQuitGracefully";
    

    而不是

    #define AppQuitGracefullyKey    @"AppQuitGracefully"
    

    我见过C或C++这样的问题,我认为这里的不同之处在于,这是专门针对目标C的,利用一个对象,在像iPhone这样的设备上,可能有堆栈、代码空间或内存问题,这些问题我还没有掌握。

    一种用法是:

    appQuitGracefully =  [[NSUserDefaults standardUserDefaults] integerForKey: AppQuitGracefullyKey];
    

    或者只是风格问题?

    谢谢。

    6 回复  |  直到 9 年前
        1
  •  59
  •   cdespinosa Martin Cote    15 年前

    如果使用静态的,编译器将在二进制文件中只嵌入字符串的一个副本,并将指针传递给该字符串,从而产生更紧凑的二进制文件。如果使用define,每次使用时都会有一个单独的字符串副本存储在源中。持续的字符串合并将处理许多重复数据消除,但您无缘无故地使链接器工作更困难。

        2
  •  14
  •   Community CDub    8 年前

    "static const" vs "#define" vs "enum" . 的主要优势 static 类型安全。

    除此之外, #define 该方法引入了内联字符串连接的灵活性,这种灵活性不能用静态变量来实现,例如

    #define ROOT_PATH @"/System/Library/Frameworks"
    [[NSBundle bundleWithPath:ROOT_PATH@"/UIKit.framework"] load];
    

    但这可能不是一个好的风格:)。

        3
  •  4
  •   Community CDub    8 年前

    在做了一些搜索之后( this 问题/答案等)我认为重要的是,当你使用字符串文字时 @"AppQuitGracefully" 创建了常量字符串,无论使用了多少次,它都将指向 相同的 对象。

    因此,我认为(如果我错了,我道歉)上述答案中的这句话是错误的: If you use a #define, there will be a separate copy of the string stored in the source on each use.

        4
  •  4
  •   Community CDub    8 年前

    实际上我也不推荐,你应该使用 extern 相反。目标C已经定义 FOUNDATION_EXPORT 哪个是 more portable 外部 如此全球化 NSString 实例如下所示:

    h

    FOUNDATION_EXPORT NSString * const AppQuitGracefullyKey;
    

    m

    NSString * const AppQuitGracefullyKey = @"AppQuitGracefully";
    

    我通常把它们放在申报文件中(比如 MyProjectDecl.h )在我需要的时候进口。

    这些方法有一些不同之处:

    • α定义 有几个缺点,比如不类型安全。确实有解决办法(例如 #define ((int)1) )但有什么意义呢?此外,这种方法还有调试方面的缺点。编译器更喜欢常量。见 this 讨论。
    • 静止的 全局球是 visible in the file they are declared.
    • 外部的 使变量对所有文件可见。这与静电形成对比。

    静态和外部的可见性不同。值得注意的是,这两种方法都没有复制字符串(甚至没有 #define )当编译器使用 String Interning 为了防止这种情况。在 this NSHipster post 他们证明:

    NSString *a = @"Hello";
    NSString *b = @"Hello";
    BOOL wtf = (a == b); // YES
    

    操作员 == 收益率 YES 只有当两个变量指向同一个实例时。正如你所看到的,确实如此。

    结论是:使用 基金会出口 对于全局常量。它是调试友好型的,在整个项目中都可见。

        5
  •  3
  •   Laurent Etiemble    15 年前

    我使用 static 当我需要从库或框架中导出nsstring符号时。我用 #define 当我在很多地方需要一根绳子时,我可以很容易地改变它。无论如何,编译器和链接器将负责优化。

        6
  •  3
  •   Hitendra Solanki    10 年前

    使用γ定义:

    无法调试标识符的值

    使用define和其他宏是预处理器的工作, 当您首先点击build/run时,它将预处理源代码,它将处理所有宏(从符号开始)。

    假设你创造了,

    #define LanguageTypeEnglish @"en"
    

    在代码中的两个地方使用了这个。

    NSString *language = LanguageTypeEnglish;
    NSString *languageCode = LanguageTypeEnglish;
    

    它将取代 “语言类型英语” 具有 @"en" 在所有地方。 所以2份 “恩” 将生成。 即

    NSString *language = @"en";
    NSString *languageCode = @"en";
    

    记住,在此过程之前,编译器不在图片中。

    在预处理完所有宏之后,编译器就会出现在图片中,它会得到这样的输入代码,

    nsstring*语言=@“en”;
    nsstring*languagecode=@“en”;
    

    并编译它。

    使用静态:

    它尊重范围并且是类型安全的。 可以调试标识符的值

    在编译过程中,如果找到编译器,

    static NSString *LanguageTypeRussian = @"ru";
    

    然后它将检查先前存储的同名变量, 如果是,它将只传递该变量的指针, 如果没有,它将创建该变量并传递它的指针,下一次它将只传递相同的指针。

    因此,使用static,在作用域内只生成变量的一个副本。