【问题标题】:Creation order of static/global objects [duplicate]静态/全局对象的创建顺序[重复]
【发布时间】:2014-09-02 07:31:54
【问题描述】:

在我的应用程序中,有 2 个全局对象。假设已经创建了一个对象的构造函数,它会访问另一个对象。幸运的是,我的应用程序正常运行了一段时间。但是由于最近 cpp 文件和编译顺序的变化,我发现全局对象创建顺序已经与我的应用程序预期的不同。

所以,我的问题是,

有没有办法控制全局对象的创建顺序。我认为静态对象也应该存在同样的问题。根据我的试用,我发现链接顺序或“o”文件改变了这一点。但它是正确的吗?没有正确的方法吗?

【问题讨论】:

    标签: c++


    【解决方案1】:

    忽略全局变量不是一个好主意的事实,您可以将对象包装在函数中。这样,它们会在首次访问时被创建,让您可以控制创建顺序:

    Foo& get_foo()
    {
      static Foo f;
      return f;
    };
    
    Bar& get_bar()
    {
      static Bar b(get_foo());
      return b;
    }
    

    使用示例:

    int main() {
        Bar& b = get_bar();
        return 0;
    }
    

    【讨论】:

    • 但是,这些对象是否可以像往常一样被其他地方访问为静态/全局对象?
    • @SujithGunawardhane - 可以通过调用上述函数来访问。
    • 哦。知道了。 :) 谢谢
    • 低开销解决方案:只需在同一个编译单元中按依赖顺序定义所有运行时初始化的相互依赖对象。奖励:您可以免费获得正确的销毁顺序(与包装函数的轻微开销相比)。
    • @Deduplicator,我怀疑有任何开销,任何体面的编译器都会优化函数调用,因为它永远不会改变。
    【解决方案2】:

    查看单例模式(复制自 yolinux)。那里有一些变化,但想法是在第一次使用类时指定创建,通过 Instance() 访问,然后用于访问代码中其他任何地方的类的唯一实例。

    class Singleton{
    public:
      static Logger* Instance(){
        if(!m_pInstance) return new Singleton;
        return m_pInstance;
      }
    
    private:
      Singleton(){};  // Private so that it can  not be called
      Singleton(Singleton const&){};             // copy constructor is private
      Singleton& operator=(Singleton const&){};  // assignment operator is private
      static Singleton* m_pInstance;
    };
    

    这部分应该放在标题之外(最好在正文文件中):

    Singleton::Singleton* m_pInstance = NULL;
    

    【讨论】:

    • 糟糕的单例模式:-(。它不是线程安全的,等等。
    【解决方案3】:

    一种很好的可维护方式是创建指向这些对象的全局指针,并以所需的顺序在单个函数(例如 main() 或其他地方)中分配它们。如果您改为进行“惰性评估”并简单地让对象在访问时创建,那么它们的顺序将不那么明显,因此可维护性也较差。

    这当然意味着如果它们没有被初始化,你将拥有空指针。

    如果 A 的 ctor 必须使用对象 B,那么 A 应该断言 B 不为空。

    (编辑:这并不是说惰性评估没有它的位置,但对于这种情况,我会亲自使用指针)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-12-31
      • 2011-12-11
      • 2011-03-24
      • 1970-01-01
      • 1970-01-01
      • 2013-06-28
      • 1970-01-01
      相关资源
      最近更新 更多