为啥/何时应该使用静态声明变量?

Posted

技术标签:

【中文标题】为啥/何时应该使用静态声明变量?【英文标题】:Why/when should I declare a variable using static?为什么/何时应该使用静态声明变量? 【发布时间】:2013-06-18 01:46:30 【问题描述】:

我没有 C/C++ 背景。在过去使用其他语言之后,我才开始学习 Objective-C。

在哪些情况下,我应该在常规 ivars 或属性上使用变量的静态声明?这样做有什么好处?

谢谢

【问题讨论】:

How SHOULD you make (and use) static libraries on the iPhone的可能重复 我不是在谈论图书馆。我说的是变量。请从我的问题中删除此横幅。谢谢。 为什么不用objective-c标签来标记objective-c问题? 【参考方案1】:

全局变量和函数

默认情况下,所有符号(全局变量和函数)都被导出(对其他源文件中的代码可见)。如果一个全局变量被声明为static,它不会被导出。这意味着它只能被当前源文件中的代码访问。

当您想要限制访问的全局变量并且不想担心名称冲突时,这很有用。例如,如果您想维护一个计数器来跟踪已创建的类实例的数量,您可以创建一个static int gInstanceCount。因为它是static,所以您会知道(1)没有其他代码可以修改该变量;(2)如果其他文件使用同名的全局变量,则不会发生任何冲突。

头文件中的静态声明

请注意,当您将某些内容放入头文件时,就好像您将该代码复制并粘贴到包含它的每个其他文件中一样。这意味着,如果您在头文件中将某些内容声明为静态,则包含它的每个文件都会获得该内容的自己的副本。

这意味着如果您在 Foo.h 中声明 static int foo,然后在 Bar.m 中写入执行 foo = 4,当您尝试访问 Other.m 中的该值时,您不一定会得到 4。

局部静态变量

您还可以将局部变量(在函数或方法主体内)定义为static。通常,局部变量在“堆栈”上分配,这意味着它们在函数执行时创建,在函数退出时释放。如果两个线程同时进入同一个函数(或者一个线程递归调用一个函数)每个线程都会获得一块新的内存来使用,并且它所做的任何事情都不会影响任何其他线程。

但是,本地 static 变量存储在“堆”上。该函数的所有执行共享相同的内存位置。此外,当函数结束时,值将保持在原来的位置。这就是为什么在 Objective-C 单例对象的 sharedInstance 方法中经常使用局部静态变量的原因。

在大多数情况下,局部 static 变量基本上就像一个全局变量,只能在声明它的函数内部看到。

【讨论】:

可见性和链接的概念是有区别的。可见性(范围)在 ISO/IEC 9899:TC3 第 6.2.1 节中定义,链接在 ISO/IEC 9899:TC3, 6.2.2 中定义 @AminNegm-Awad 这很有趣!我可能对我的条款有点松懈,但我正在努力做出一个有用的答案以及一个准确的答案。差异会使我上面写的任何内容无效吗?如有必要,我将对其进行编辑。 是:“(使其他源文件中的代码可见)” 翻译单元中的变量在另一个翻译单元中不可见。如果它在翻译单元中声明,它是可见的。然后,它被链接。没有出口。在标题中使用静态似乎没有意义。为什么 Foo.h 应该在每个翻译单元中创建一个变量? Foo.m 无法访问它。 @AminNegm-Awad 是的,头文件中的静态通常是一个错误。这就是为什么我想提请注意它。关于我对“导出”的使用:在我看来,这个问题的抽象是可以接受的,而没有深入了解编译和链接过程的很多细节。【参考方案2】:

static 关键字用于为全局变量提供范围。通常,在函数外部定义的全局变量具有公共范围,并且对项目中的所有 .m 或 .c 文件可见。将变量设为静态允许您拥有一个“全局”变量,该变量的范围(可见)仅限于包含变量定义的 .m 或 .c 文件。这允许您在单个源文件中拥有一个可由多个函数共享的变量,同时避免潜在的命名冲突。另外值得注意的是 extern 关键字,它允许您指示特定的全局变量在不同的源文件中初始化但在此源文件中使用。

【讨论】:

【参考方案3】:

关键字static 在C 中被过度使用。它意味着几个不同的东西。在某些情况下,它只是意味着该字段仅在该文件的其余部分(编译单元)中被理解。换句话说,它不能从其他文件链接到。

在 Java 和 C++ 中,静态类成员是在类级别定义的,而不是在单个对象级别定义的,因此该类(或其子类之一)的所有对象共享一个值。不幸的是,恕我直言,Objective C 不支持这一点。取而代之的是 use 文件级别的静态变量。

【讨论】:

【参考方案4】:

如果您不知道是否需要静态变量,则可能不需要。

您可能使用静态变量的一个原因是提供一个类变量(即,一个用于整个类的变量,而不是一个实例变量,一个类的每个实例都有它自己的副本)。

This question(及其接受的答案)解释了如何使用静态变量来模拟 Objective-C 中的类变量。

【讨论】:

static 与作用域无关。 虽然static 在技术上与范围无关,但它确实与 linkage (用于文件级静态变量和函数)有关,它可以有很多效果一样。 没有。范围描述了在源中的某个位置使用标识符的可能性。 (“全局”)标识符在翻译单元中可用,如果它被声明并且仅当它被声明时。这不取决于是否声明了外部链接、内部链接或无链接。联动描述的效果,是否if 一个(“全局”)变量在不同的翻译单元中被声明了两次都是一起出来的。【参考方案5】:

首先:在这种情况下,“object”指的是“c objects”,用非常简单的话来说,就是在运行时存在的东西。它与 OOP 或 Objective-C 意义上的对象无关。您可以将对象视为 var。

static 与作用域无关。外部标识符上的static(= 在块外声明)具有内部链接。链接结果在 ISO/IEC 9899:TC3 第 6.2.2 节中定义。范围在第 6.2.1 节中定义。 简而言之,内部链接意味着不同翻译单元(“.m 文件”)中的两个标识符表示的不是同一个对象,而是不同的对象。每个翻译单元都有其“自己的”对象。

如果标识符不是用静态存储类声明的外部(= 块内),则它具有从程序开始执行到程序停止运行的生命周期。

【讨论】:

以上是关于为啥/何时应该使用静态声明变量?的主要内容,如果未能解决你的问题,请参考以下文章

java:在java中为啥静态变量没有this引用?

为啥要在 main 中声明一个静态变量?

静态方法何时使用

java中静态成员变量、实例变量、局部变量何时创建、何时销毁?

为啥 main() 不能在 C 中声明为静态的?

为啥线程过程应该是静态或成员函数