Objective-C中的const与static NSString有何区别?

47

这两行代码都在实现文件中,在 @implementation 声明之前。

NSString * const aVar = @"aVarStringValue";

static NSString *aVar = @"aVarStringValue";

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

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

而第一个const声明则会在每次访问时分配吗?

3个回答

103

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

const则表示引用不能被修改和/或重新赋值;并且与它的创建方式无关(编译器可能会优化常量)。

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


希望我能给你一个赞,但是bbum先到了。 - firstresponder
@firstresponder - 不是bbum吗?notnoop在bbum之前回答了整整一天(至少在东部标准时间上是这样的。在其他时区的同一天早些时候,他比bbum早了一分钟回答。) - ArtOfWarfare
1
@notnoop 这个答案有任何参考来源吗? - Mingming

49

static 只改变了变量的作用域,而不影响其如何声明或存储。

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

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

const 是相互独立的,在 NSString 引用的情况下,几乎完全不相关。


3
谢谢。这句话:"你可以在某个头文件中重新声明字符串为 extern NSString *aVar; 并从任何地方访问它",确实让我理解了。 - firstresponder
6
实际上,const 并非完全无关紧要 -- 它防止您将 aVar 更改为指向不同的 NSString 对象。 - David Hull
实际上,“static”也表示变量的存储方式。它在整个程序的生命周期内都存在。 - Philip007

6
为了解决关于使用 static 和位置的讨论,根据 C99/GNU99 规范(通常用于 Objective-C 代码):
  • static

    • 是存储类说明符

    • 默认情况下,具有文件级别作用域的对象具有外部链接性

    • 具有静态说明符的文件级别作用域的对象具有内部链接性。
  • const

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

    • 应用于左侧实例 - 即

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

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

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

      • const MyObj * myVar; - 非限定指向常量限定对象类型的指针
因此:

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

如果没有使用 static 关键字,变量名称将成为全局变量,并可能导致应用程序中的名称冲突。


我最近才接触到声明所有本地变量的 Objective-C 代码,像这样NSMutableArray * const myArray = [NSMutableArray new];。我从未在此情况下使用过 const,现在我很困惑是否一直都用错了? - MrBr
请注意,这仅适用于在全局、文件级别上使用 static 关键字的情况。在方法体内部,其含义完全不同,它表示存储空间在文件的数据段中分配一次,而不是存储在堆栈或堆中,并且在该方法的调用之间共享。 - dgatwood

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接