【问题标题】:Why is assigned a nil to singleton's static variable为什么将 nil 分配给单例的静态变量
【发布时间】:2012-11-16 20:55:37
【问题描述】:

使用这个有什么好处:

+ (CardPainter*) sharedPainter {
    static CardPainter* sp = nil;

    if (nil == sp) {
        sp = [[CardPainter alloc] init];
    }

    return sp;
}

而不是这个:

+ (CardPainter*) sharedPainter {
    static CardPainter* sp = [[CardPainter alloc] init];

    return sp;
}

静态变量初始化只执行一次,所以我看不出前者有什么好处。

【问题讨论】:

标签: objective-c static singleton null


【解决方案1】:

嗯,在编译器级别有几个重叠的原因......最简单的考虑是静态变量存储在已编译应用程序的专用数据部分中,它只是按原样映射到内存中。所以编译器必须在编译时准确地知道那是什么。根据定义和实践,任何 Objective-C 方法调用的结果在编译时都是不可预测的——你永远不知道在运行时不会发生“有趣”的事情来改变该方法调用的行为,所以你不会确定会返回什么。

这与 e.g. 有点不同。 C++,出于各种原因(一个关键是 C++ 有构造函数,而 Objective-C 没有)。但即使在 C++ 中,由于以下几个原因,它仍然不受欢迎:

  1. 构造函数顺序是不可预测的,但构造函数相互依赖很容易也很常见,这意味着您的程序在运行时可能会出现未定义的行为(包括数据损坏或崩溃)。
  2. 初始化大量重要对象的成本可能很高。在启动时一起完成这一切可能会很有效,但它会使您的应用启动速度变慢,这要糟糕得多。

后一点同样适用于 Objective-C。您可以避免在发布时执行的操作越多,而是按时按需执行,用户体验通常就越好。

[ 请注意,“无静态对象实例”规则有一个值得注意的例外,那就是 @"foo" 形式的字符串。这些实际上在您的应用程序的数据部分中编码为真实实例(特殊的 NSString 子类),它们只是在启动时被映射并按原样神奇地工作。但这是经过精心设计的,编译器和运行时在这方面紧密耦合,以确保一切顺利。它不会也不能普遍适用。 ]

【讨论】:

    【解决方案2】:

    因为如果你不问,你会在任何时候调用“sharedPainter”时初始化“*sp”,丢失任何数据。

    所以,如果你问 sp 是否为 nil 并且答案是 FALSE 意味着“sp”已经初始化并且它返回实例。如果答案是真的,那意味着 sp 没有被初始化,在这种情况下你调用了 init 函数。

    【讨论】:

    • 不是检查指针是否为nil,而是为什么不在初始化行直接调用alloc init
    • 好吧,其实static的声明不能在sharedPainter函数上,必须在实现之前。
    • @PatricioIgnacioFariaValdivi:嗯……什么?当然你可以在函数中包含静态变量
    • 我不记得说“你不能”。是的,你可以。但在这种情况下,你不应该。您每次都在“重新实例化” sp。
    • 没有。除了第二个示例无法编译之外,出于我在回答中解释的原因,即使它编译了它也不会像您描述的那样运行。静态变量仅在启动时(基本上)一次初始化为其分配的值。如果不是,它们与非静态局部变量没有什么不同,第一个示例的形式也没有任何意义。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-10-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-10
    • 2022-10-05
    • 1970-01-01
    相关资源
    最近更新 更多