全局静态动态分配对象C ++

时间:2012-05-29 15:41:19

标签: c++ static heap global

我对动态分配的静态全局对象有非常具体的问题。在我的项目中,我有很少的对象,我需要在整个应用程序生命周期中从线程的各个位置访问。我想在应用程序初始化时创建它并在应用程序退出时解压缩。所以我试着跟着,

头文件:MyObjectFactory.h

class MyObjectFactory{
   public:
      static MyObject* GetMyObject();
};

源文件:MyObjectFactory.cpp

static MyObject* gMyObject = 0;

MyObject* MyObjectFactory::GetMyObject(){
    if(gMyObject == 0)
    {
        gMyObject = new MyObject();
    }
    return gMyObject;
}

这段代码似乎很有用,但我想澄清一些事情。

  1. 对象将仅创建一次,然后将返回对象的引用。 (我想要这个,因为MyObject封装了很少的系统资源,比如文本文件)
  2. 当Application退出时,MyObject会被销毁。
  3. 在哪里创建对象Heap(因为我正在使用new)或全局内存(因为我使用静态)?或者我违反任何OOP原则?
  4. 可以从多个线程调用MyObjectFactory :: GetMyObject()吗?
  5. 这是一种与Singleton有些相似的好方法吗?
  6. 请让我知道你的意见。

    非常感谢你!

3 个答案:

答案 0 :(得分:2)

  

只创建一次对象,然后返回对象的引用。 (我想要这个,因为MyObject封装了很少的系统资源,如文本文件)

  • MyObject*是指针类型,而不是引用类型。 gMyObject是指向MyObject的指针类型的变量。
  

当Application退出时,MyObject会被销毁。

  • 没有,没有人在你的指针上调用delete,所以你有泄漏。
  

在哪里创建对象Heap(因为我正在使用new)或全局内存(因为我使用静态)?还是我违反任何OOP原则?

  • 如果您使用new,则会在'heap'处创建对象。 static仅适用于指向对象的指针,而不适用于对象本身。
  

可以从多个线程调用MyObjectFactory :: GetMyObject()吗?

  • 不是,如果您有并发线程并且尚未构建对象,则可以导致多次初始化。
  

这是一种与Singleton有些相似的好方法吗?

  • 不是。或许它是,但单身通常是一种不好的方式来实现某些东西(我只说通常是)。

答案 1 :(得分:2)

实现正确破坏和正确初始化以及最小头痛的标准方法使用块本地静态,如下所示:

<强> foo.hpp:

struct Foo
{
    static Foo & get();
    // ...
};

<强> Foo.cpp中:

#include "foo.hpp"

Foo & Foo::get()
{
    static Foo impl;
    return impl;
}

现在,您可以在代码中的任何位置说Foo::get()。没有指针,没有动态分配,没有任何东西泄露。一个真正的静态单身人士。

答案 2 :(得分:0)

  

只创建一次对象,然后返回对象的引用。

如果您的程序是单线程的,那么(尽管在您的示例中它返回的是指针而不是引用)。否则存在两个线程创建对象的单独副本的危险;或者实际上发生了其他任何事情,因为在这种情况下行为是不确定的。

  

当Application退出时,MyObject会被销毁。

不,使用new创建的对象只会被delete销毁,而不会自动销毁,因此此对象会被泄露。这是否是一个问题取决于它使用的所有资源是否由系统自动回收。

  

在哪里创建对象Heap(因为我正在使用new)或全局内存(因为我使用静态)?

该对象是从免费商店(又名堆)分配的;指向它的指针是静态的。

  

可以从多个线程调用MyObjectFactory :: GetMyObject()吗?

只有在可以确保在任何一个对象调用之前已经创建了对象时才会这样做。

  

这是一种与Singleton有些相似的好方法吗?

在C ++中没有很好的方法可以实现这一点。最好的方法是完全避免全局可访问的对象;在某处创建它,并将引用传递给任何需要它。

如果你真的想要一个全局对象,那么有几个选项,每个都有自己的死亡陷阱:

  • 一个简单的全局对象。如果您有多个这样的初始化订单Fiasco,请注意它们之间存在依赖关系。
  • 包含静态对象的函数,返回对此的引用。保证在使用它时初始化,并且在符合C ++ 11的实现(以及许多早期的实现)上是线程安全的。但是,在程序关闭期间,存在一种危险,即它可能在其他仍在尝试访问它的静态对象之前被销毁 - 您可以通过动态分配和泄漏对象来避免这种情况,就像在您的方法中一样。确保线程安全构建可能还有一些运行时开销。
  • 一个懒惰分配的动态对象(就像你一样),只要你确保在启动多个线程之前初始化它,或者添加线程安全性(这不是完全简单的,并且会增加运行时开销)。