2012-01-26 154 views
1

我正在開發一個庫,用戶應該能夠使用靜態全局實例。這些實例(前主中運行),然後在可以使用另一個全局矢量自己註冊......自注冊全局對象

目前,它會有點像這樣...

class A; 

std::vector<A*> v; 

class A { 
public: 
    A (int i) : i(i) { 
     v.push_back(this); 
    } 

    int get() const { 
     return this->i; 
    } 
private: 
    int i; 
}; 

A a(1); 
A b(2); 

int main() 
{ 
    for (A* const& c : v) 
     std::cout << c->get() << std::endl; 

    for (std::vector<A*>::iterator i = v.begin(); i != v.end(); i++) 
     delete *i; 

    return 0; 
} 

不過,這恐怕代碼會泄漏......更重要的是,當我不希望用戶明確地刪除向量的內容(無論如何他們會忘記它),它應該在main的結尾自動發生。

還有其他解決方案嗎?我想使用一個std :: unique_ptr向量,但顯然他們不這樣工作...

+2

「*我想使用std :: unique_ptr的向量,但顯然他們不這樣工作...... *」請詳細說明。此外,您__不應嘗試「刪除」靜態分配的對象(此代碼不會像您所建議的那樣泄漏,但會刪除對象兩次會調用UB)。 – ildjarn

+1

由於您在靜態實例上工作:a)該代碼是如何泄漏的,以及b)爲什麼地球上的指針指向靜態對象時會調用delete。總之,我會說你的代碼(如你所示)是越野車,但它不應該泄漏 – Grizzly

回答

4
  1. 您的代碼不會泄漏。分配內存的唯一東西是std::vector,並且它會自行清理破壞。
  2. ab在執行結束時被正確銷燬並釋放。
  3. 您不應delete未分配new的東西。

而且,你是靠v構造ab之前被初始化。您應該懶惰地初始化v(請參閱下文)。

std::vector<A*>& global_v() 
{ 
    static std::vector<A*> v; 
    return v; 
} 

// use global_v() instead of v in the A constructor. 

要得到你想要的東西,只需刪除刪除這些對象的循環。

Here's您的代碼在刪除循環並添加了一些調試輸出的情況下運行。注意兩個對象都被正確銷燬。

+0

刪除只刪除這些對象的循環只有他想要的東西,如果這真的都在一個單一的翻譯單元內 - 假設一個具有多個翻譯單元的真實項目,並不能保證在對象試圖插入它之前構造'v'。 – ildjarn

+0

我認爲他希望用戶將「新A」放入向量中,但不會讓用戶不得不「刪除」它們。 –

+0

@SethCarnegie:他在說什麼?在第一句話中,他說他們將是靜態的全局實例。 @ildjam:確實,'v'應該被延遲初始化。我會將其添加到我的答案中。 –