【问题标题】:why doesn't setting a static variable to nil defeat purpose of static variable? [duplicate]为什么不将静态变量设置为零会破坏静态变量的目的? [复制]
【发布时间】:2014-03-24 06:33:43
【问题描述】:

下面的代码来自 Big Nerd Ranch iOS 编程书,第 3 版。它是一个类方法,用于检查单例类 BNRItemStore 是否已被实例化。如果有,则返回单例实例,如果没有,则创建它。我不明白的部分是静态变量。我知道静态变量保持状态,但是,不会再次调用该方法将 *sharedStore 重置为零?也就是说,一旦再次调用该方法,这不是一个会删除单例实例创建的赋值吗?

static BNRItemStore *sharedStore = nil;

方法

+(BNRItemStore *)sharedStore
{
   static BNRItemStore *sharedStore = nil;
   if (!sharedStore)
       sharedStore = [[ super allocWithZone:nil ] init ];
   return sharedStore;
}

【问题讨论】:

  • 这是 C 的 static 实现的一个怪异之处:无论静态变量在哪里声明,在声明语句中发生的任何初始化都只执行一次。

标签: ios objective-c


【解决方案1】:

不幸的是,C 术语确实令人困惑。 static 与单身人士、静止不动、不改变或类似的事情无关。它与存储发生的级别有关。

在方法/函数中声明的变量通常是一个自动变量,这意味着它在作用域结束时不复存在(即执行到达周围花括号的末尾)。然而,声明为静态的变量存储在包含代码的文件级别;一旦文件被加载,这个变量仍然存在,即使它是在方法/函数中声明的。

现在我们来看看如何知道这个变量是否曾经被赋值过,因为你只想给它赋值一次。理论上,static 变量在最初声明时的值为零。因此,如果你只是说

   static BNRItemStore *sharedStore;

...代码可能会起作用,因为零对于一个实例来说是 nil,所以我们可以针对 nil 进行测试并仅在这种情况下分配一个值。但是,确保双重确定并没有什么坏处。因此,我们通常在声明变量时将其初始化为 nil,这样我们就可以确保我们的 nil 测试将在第一次工作。

正如您已经被告知的那样,该初始化程序将只生效一次,因为在那之后,值仍然存在,因此该变量不再需要再次初始化(并且永远不会) .

【讨论】:

  • 一种解释是“静态”一词描述了变量在内存中的存储位置。一个普通的自动变量会根据它在调用堆栈中的位置自动存储在内存中的不同位置,但是静态变量总是存储在同一个位置,所以当在不同的上下文中再次访问它时,它仍然包含相同的价值。
【解决方案2】:

代码没问题,初始化器只在第一次被调用。

【讨论】:

  • 我想你误解了我的问题。我在问为什么初始化程序不会被第二次调用。换句话说,如果我第二次调用 sharedStore,静态变量 *sharedStore 不会设置为 nil,这意味着没有共享存储,所以 if(!sharedStore) 中的代码会运行?
  • 这样更有帮助吗? stackoverflow.com/questions/5567529/… 这种行为在 Objective C 中是一样的。
  • 是的,现在我明白了,谢谢
  • “初始化器只在第一次被调用” 或者更准确地说,初始化器在编译时被“烘焙”——所以初始值是程序的可执行文件(如const 值的工作方式)以及当程序启动并将可执行文件的内存布局加载到堆栈上时,初始值将与其他所有静态值一起加载(static vars、consts、@ 987654326@es)。
【解决方案3】:

语言规范保证静态初始化器只被执行一次,(这实际上是在应用程序启动时完成的,而不是作为函数执行的一部分)所以静态变量只会在函数第一次被执行时为 nil执行。

【讨论】:

    猜你喜欢
    • 2014-01-15
    • 1970-01-01
    • 2020-06-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多