在接口实现中,静态变量的含义是什么?

73

我不太理解在接口实现中定义静态变量的含义。在方法中,我了解它们与局部变量的区别,但是在接口实现中直接定义时不清楚差别。

看看这些例子。从实际上讲,这两个有什么区别?

#include "MyClass.h"

@implementation MyClass
int myInt;
...
@end

并且:

#include "MyClass.h"

@implementation MyClass
static int myInt;
...
@end

myInt 在两种情况下都对所有方法可见,如果我正确解释了我运行的测试,myInt 在不同类实例中将是相同的变量。


请查看https://dev59.com/Rm445IYBdhLWcg3wQX6G#4965145。 - Kyle Clegg
4个回答

93

不幸的是,它在使用地方有不同的影响。

静态函数:
默认情况下,所有函数都具有全局作用域。静态修饰符可以让您将函数的范围限制为当前文件。

静态局部变量:
当您在局部变量上使用静态修饰符时,函数会在调用之间“记住”其值。例如,在以下代码片段中,currentCount变量永远不会被重置,因此我们可以让countByTwo()为我们记录计数,而不是将计数存储在main()内的变量中。

// main.m
#import <Foundation/Foundation.h>

int countByTwo() {
    static int currentCount = 0;
    currentCount += 2;
    return currentCount;
}

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        NSLog(@"%d", countByTwo());    // 2
        NSLog(@"%d", countByTwo());    // 4
        NSLog(@"%d", countByTwo());    // 6
    }
    return 0;
}

使用static关键字不会影响局部变量的作用域。
阅读有关static关键字的更多信息。


8
static关键字将强制其所在行仅在整个应用程序运行期间执行一次--无论调用次数多少! - mfaani
静态变量“currentCount”存储在内存的哪个位置?它不能在countByTwo的框架中,因为该框架在函数结束时被释放。那么它存储在哪里? - Enrique
@Enrique 在同一数据/ bss 区域中,与其他“全局”变量所在的位置相同,只是作用域是本地的。 - BjornW

72

在这个上下文中,'static' 关键字与普通的 C 语言中含义相同:它将 myInt 的作用域限制在当前文件中。


12
在 @implementation 内部定义一个非局部变量和在外部定义没有任何区别。 - sigjuice
9
假设您在两个不同的实现文件中声明了 int Variable;,则在构建时会出现错误,因为存在重复的符号。 - Denis Mikhaylov
1
这是否意味着它充当了“私有”访问修饰符? - glesage
1
不,C++中的“private”关键字只是在谁可以访问变量或方法上添加编译器强制限制。“static”将其范围限定为所在文件,这非常不同。 - smorgan
我的猜测是许多不了解静态的人可能也不知道编译单元是什么,所以我稍微简化了一下。 - smorgan
显示剩余2条评论

24
在C和Objective-C中,静态变量是为程序的整个生命周期分配的变量。这与自动变量不同,后者的生命周期存在于单个函数调用期间;以及动态分配的变量(如对象),可以在不再使用时释放内存。更简单地说,静态变量的值在所有函数/方法调用期间保持不变。当在函数外部声明时,静态变量对其所在文件中的所有内容都可见;当在函数或方法内部声明时,它仅在该函数或方法内部可见,但值在调用之间保留。
请查看完整的解释:

https://dev59.com/Rm445IYBdhLWcg3wQX6G#4965145


18
从苹果公司的《Objective-C编程语言》中得知,声明一个static变量将其作用范围限制在类中,并且仅限于文件实现的部分。 (因此,与实例变量不同,静态变量不能被子类继承或直接操控)。

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