C ++ static,extern用于全局数据

时间:2013-07-05 19:50:27

标签: c++

我一般都是C ++和OOP的新手,一直在努力学习有效或“正确”的做事方法,但我仍然遇到麻烦。

我正在创建一个DataStore类,用于保存其他类/对象的数据。这个类只会有一个实例/对象;但是,实际上并不需要成为对象/实例,因为它是全局数据。在这种情况下,我觉得这只是提供范围的一种方式。所以,我想直接更改类成员而不是传递对象。我已经阅读过关于static和_extern的内容,但我无法确定是否可行,或者是否还有其他更好的内容。

现在我正在传递一个创建的对象以更改它的数据,但我宁愿将该类作为“本身”而不是“自身的实例”进行访问,同时仍然保留它作为对象的想法

4 个答案:

答案 0 :(得分:3)

通常情况下,这种问题(你需要一个,但只有一个 - 你确定你永远不需要更多),通过使用“单一”模式来解决。

class Singleton
{
  public:
    static Singleton* getInstance() 
    { 
       if (!instance) instance = new Singleton(); 
       return instance;
    }

    int getStuff() { return stuff; }


  private:
    Singleton() { stuff = 42; }
    static Singleton *instance;
    int stuff; 
};

然后在一些合适的.cpp文件>

static Singleton *instance;

或直接使用全局变量:

class Something
{
 public:
   Something() { stuff = 42; }

   int getStuff() { return stuff; }

 private:
   int stuff; 
}

extern Something global_something;    // Make sure everyone can find it. 

在一个.cpp文件中:

Something global_something; 

由于这两者本质上是一个全局变量解决方案,我希望有人不喜欢全局变量会将其下调,但如果你不想在任何地方传递你的类对象,那么全局变量并不是一个糟糕的主意。您只需要意识到全局变量作为一般解决方案不一定是个好主意。如果您突然需要多个(因为您决定更改代码以支持两个不同的存储,或者其他任何东西),它可能很难跟踪正在发生的事情,并且它肯定会变得混乱 - 但这也适用于单例。 / p>

答案 1 :(得分:1)

编辑:在评论中,OP解释说,数据存储将由在多个线程中运行的代码读取,并由一个线程中的代码更新。我之前的回答不再适用。这是一个更好的答案。

不要使用全局变量来保存商店的实例。这将为许多可能困扰你很长时间的细微错误打开大门。您应该为阅读线程提供对商店的只读访问权限。您的写作线程应该具有读写访问权限。

确保数据存储中的读取方法已正确标记为const。然后创建数据存储的单个实例,并将指针放在const全局变量中。你的编写线程应该有另一种获取非const指针的机制(按照@Mats的建议添加GetInstance公共静态方法。)

我之前的回答: 如果您确定将始终只有一个数据存储实例,请不要传递它。

全球变量不受欢迎,有些语言(Java和C#)完全取缔它们。因此,在C#和Java中,您使用的是静态类成员,这实际上是相同的(具有完全相同的问题)。

如果你可以把你的单个实例放在一个const全局变量中,你应该没问题。

如果您正在进行任何类型的多线程处理,您需要确保您的商店是线程安全的,否则会发生非常糟糕的事情。

答案 2 :(得分:1)

您可以使用有争议的Singleton模式,或者您可以使用Mark Radford (Overload Journal #57 – Oct 2003) SINGLETON - the anti-pattern!文章中描述的PARAMETERISE FROM ABOVE方法之一。

上面的参数方法(在他看来)加强了封装并简化了初始化的困难。


经典的懒惰评估和正确销毁的单身人士:

class S
{
    public:
        static S& getInstance()
        {
            static S    instance; // Guaranteed to be destroyed.
                                  // Instantiated on first use.
            return instance;
        }
    private:
        S() {};                   // Constructor? (the {} brackets) are needed here.
        // Dont forget to declare these two. You want to make sure they
        // are unaccessable otherwise you may accidently get copies of
        // your singleton appearing.
        S(S const&);              // Don't Implement
        void operator=(S const&); // Don't implement
};

但请注意:这不是线程安全的。

see here for good StackOverflow post about Singletons

答案 3 :(得分:1)

我为在程序执行期间大部分时间都有1个实例的对象执行此操作。

class Object {
private:
  Object();
  friend Object & GetObject();

public:
   ...
};

inline Object & GetObject() {
    static Object O;
    return O;
}

1)这比单身人士更简洁 2)这可以避免全局对象的陷阱,例如未定义的初始化顺序。