2012-05-29 31 views
0

我對動態分配的靜態全局對象有非常具體的問題。在我的項目中,我有幾個對象,我需要在整個應用程序生命週期的各個線程中訪問各個線程。我想在應用程序初始化時創建並在應用程序退出時破壞它。所以,我想下面,全局靜態動態分配對象C++

頭文件: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. MyObject在Application退出時被破壞。
  3. 在哪裏會創建對象堆(因爲我使用新的)或全局內存(因爲我使用靜態)?還是我違反任何面向對象的原則?
  4. 可以從多個線程調用MyObjectFactory :: GetMyObject()嗎?
  5. 這是一個有點類似於Singleton的好方法嗎?

請讓我知道您的意見。

非常感謝你!

+0

'MyObject *'是一個指針,而不是一個引用... –

+0

無論是「靜態」還是「動態」,你都不能同時擁有這兩者。 –

+0

是否有特定的要求,該對象是使用'new'創建的?否則,只要使它成爲全局'MyObject theObject;'。 –

回答

2

對象將只創建一次,然後將返回對象的引用。 (我想這是因爲myObject的封裝,如文本文件很少的系統資源)

  • MyObject*爲指針類型,不是引用類型。 gMyObject是指向MyObject的指針類型變量。

當應用程序退出時MyObject被破壞。

  • 沒有,沒有人在你的指針調用delete讓你有泄漏。

會在哪裏對象創建堆(因爲我使用新的)或全局存儲器(如我使用靜態的)?還是我違反任何面向對象的原則?

  • 如果使用的是new,在'堆'創建對象。 static僅適用於指向您的對象的指針,而不適用於對象本身。

可以從多線程調用MyObjectFactory :: GetMyObject()嗎?

  • 這不,你可導致多種初始化,如果你有併發線程和對象尚未建立。

這是一個有點類似於Singleton的好方法嗎?

  • 不是。或者,也許是這樣,但單身人士通常是一個不錯的方式來實現某些東西(我只說通常是)。
+0

更確切地說,'MyObject *'是一種類型,但我現在是一個很好的學生。 –

+0

@ phresnel:Pedantry接受,回答編輯。 –

+0

我很慚愧,繼續我的貞操,請赦免。但'gMyObject'是一個指針。我可以建議'gMyObject是指向MyObject的指針類型的變量嗎?我心情不好。不理我。或者'gMyObject是一個指針變量'。 –

2

的標準方式達到既正確的破壞,並以最少頭痛正確初始化使用塊局部靜態,這樣的:

foo.hpp:

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

Foo.cpp中:

​​

現在你可以在代碼中的任何地方說Foo::get()。沒有指針,沒有動態分配,也沒有任何泄漏。一個真正的靜態單身人士。

+0

根據OP問題#4,您可以添加與線程安全相關的內容以及C++ 11和C++ 03的不同之處。 –

+0

@ K-ballo:初始化是線程安全的,其他一切都是OP的問題。 (但這與單例無關,這只是一般的編程。) –

+0

複雜'Foo'線程安全嗎? C++ 03中沒有競爭條件嗎? –

0

對象將只創建一次,然後將返回對象的引用。

如果你的程序是單線程的,是的(雖然在你的例子中它返回一個指針而不是引用)。否則,會有兩個線程創建對象的單獨副本的危險;或事實上發生其他事情,因爲在這種情況下行爲是不確定的。

當Application退出時MyObject被破壞。

不,用new創建的對象只會被delete銷燬,永遠不會自動地銷燬,所以這個對象被泄漏。這是否是一個問題取決於它使用的所有資源是否被系統自動回收。

在哪裏會創建對象堆(因爲我使用新的)或全局內存(因爲我使用靜態)?

該對象從免費商店(aka堆)分配;指向它的指針是靜態的。

可以從多個線程調用MyObjectFactory :: GetMyObject()嗎?

只有當您可以確保該對象在其中一個被調用之前已經被創建。

這是實現有點類似於Singleton的好方法嗎?

有實現在C++中沒有很好的辦法。最好的方法是完全避免全球可訪問的對象;在某處創建它,並將其引用到任何需要它的地方。

如果你真的想要一個全局對象,然後有幾個選項,每個都有自己的deathtraps:

  • 一個簡單的全局對象。請注意初始化命令Fiasco,如果您擁有多個這樣的產品,並且它們之間存在依賴關係。
  • 包含靜態對象的函數,返回對此的引用。這是保證在你使用它時被初始化的,並且在符合C++ 11的實現(以及許多早期的實現)上是線程安全的。但是,在程序關閉期間,可能會在其他靜態對象仍然嘗試訪問它之前被銷燬 - 您可以通過動態分配和泄漏對象來避免這種情況,就像在您的方法中那樣。確保線程安全構建也可能會產生一些運行時間開銷。
  • 一個延遲分配動態的物品(如你),只要你要麼確保它推出多個線程前初始化,或添加線程安全(這並不簡單,並會增加運行時的開銷)。