【问题标题】:const vs static NSStrings in Objective-CObjective-C 中的 const 与静态 NSStrings
【发布时间】:2010-12-21 03:05:17
【问题描述】:

这些行都在@implementation 声明上方的实现文件中。

NSString * const aVar = @"aVarStringValue";

static NSString *aVar = @"aVarStringValue";

据我了解,第二个 static 仅在应用程序的生命周期内分配一次,这一事实有助于提高性能。

但这是否意味着它本质上是内存泄漏,因为那块内存永远不会被释放?

相反,第一个const 声明是否在每次访问时都会被分配?

【问题讨论】:

    标签: objective-c cocoa cocoa-touch


    【解决方案1】:

    Objective-C(和 C/C++)中的static 关键字表示变量的可见性。静态变量(不在方法中)只能在特定的.m 文件中访问。另一方面,静态局部变量只分配一次。

    另一方面,const 表示不能修改和/或重新分配引用;并且在创建方式上是正交的(编译器可能会优化 consts)。

    值得一提的是NSString 字面量在应用程序的生命周期中被初始化并且永远不会被销毁。它们被分配在内存的只读部分中。

    【讨论】:

    • 希望我能给你打勾,但 bbum 是第一个。
    • @firstresponder - 没有 bbum 不是吗? notnoop 在 bbum 前一整天回答(无论如何,在美国东部标准时间。他在同一天在其他时区提前一分钟回答。)
    • @notnoop 这个答案有什么参考来源吗?
    【解决方案2】:

    static 只改变变量的作用域,而不改变它的声明或存储方式。

    在这两种情况下,编译器都会创建一个常量版本的 NSString 实例,该实例存储在 mach-o 文件中。因此,只有一个实例(请注意,您可以更改行为以使字符串在加载 mach-o 时动态创建,但仍然只有一个实例)。

    static 只是将aVar 变量标记为仅在编译单元(文件)范围内可见。如果没有static,您可以在某处的标头中将字符串重新声明为extern NSString *aVar;,并可以从任何地方访问它。

    const 是正交的,在 NSString 的情况下,引用几乎完全不相关。

    【讨论】:

    • 谢谢。这一点:'你可以将字符串重新声明为 extern NSString *aVar;在某个地方的标题中,并且可以从任何地方访问它'真的把它带回家了。
    • 实际上const 并非完全无关紧要——它会阻止您将aVar 更改为指向不同的NSString 对象。
    • 其实static也表示变量是如何存储的。它代表程序的整个生命周期。
    【解决方案3】:

    为了解决所有可能的关于static的需要和const的位置的讨论:

    根据 C99/GNU99 规范(通常用于 Objective-C 代码):

    • static

      • 是存储类说明符

      • 默认情况下文件级范围的对象具有外部链接

      • 具有静态说明符的文件级范围的对象具有内部链接
    • const

      • 是类型限定符(是类型的一部分)

      • 应用于紧邻左侧实例的关键字 - 即

        • MyObj const * myVar; - 指向 const 限定对象类型的非限定指针

        • MyObj * const myVar; - 指向非限定对象类型的 const 限定指针

      • 最左边的用法 - 应用于对象类型,而不是变量

        • const MyObj * myVar; - 指向 const 限定对象类型的非限定指针

    周四:

    static NSString * const myVar; - 指向具有内部链接的不可变字符串的常量指针。

    缺少static 关键字将使变量名全局化,并可能导致应用程序内的名称冲突。

    【讨论】:

    • 我最近刚刚使用了声明所有局部变量的 Objective-C 代码,例如 NSMutableArray * const myArray = [NSMutableArray new];。我从来没有用过const,现在我很困惑,如果我一直做错了??
    • 请注意,这在全局文件级上下文中使用静态时才为真。在方法体内,含义完全不同,表示存储在文件的数据段中分配一次,而不是存储在堆栈或堆上,并且在该方法的调用之间共享。跨度>
    猜你喜欢
    • 1970-01-01
    • 2020-08-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-03
    • 1970-01-01
    • 1970-01-01
    • 2014-05-28
    • 2015-06-07
    相关资源
    最近更新 更多