2013-11-23 90 views
6

在我的C++代碼中,我有一個類Object,它配備了一個int類型的id字段。現在我想創建一個Object *類型的指針向量。首先我試過創建指針的C++向量

vector<Object*> v; 

for(int id=0; id<n; id++) { 
    Object ob = Object(id); 
    v.push_back(&ob); 
} 

但是這樣做失敗了,因爲這裏同樣的地址只是重複了n次。如果我使用新的運算符,我會得到我想要的,但我想避免動態內存分配。然後我認爲我需要的是以某種方式在for循環之前聲明n個不同的指針。這個簡單的方法是聲明一個數組,所以我這樣做:

vector<Object*> v; 
Object ar[n]; 

for(int i=0; i<n; i++) { 
    ar[i] = Object(i); 
} 

for(int i=0; i<n; i++) { 
    v.push_back(ar+i); 
} 

是否還有可能獲得一個內存泄漏,如果我做這種方式?在我看來,通過數組聲明也有點笨拙。有沒有其他的方法來創建指針的矢量,但避免手動內存管理?

編輯:爲什麼我想要指針而不是簡單的對象?

嗯,我修改了一下原來的實際情況,因爲我以這種方式思考我可以用最簡單的形式表示問題。無論如何,我仍然認爲這個問題可以在不知道我爲什麼需要指針向量的情況下得到解答。

其實我有

Class A { 
protected: 
    vector<Superobject*> vec; 
... 
}; 

Class B: public A {...}; 

Class Superobject { 
protected: 
    int id; 
... 
} 

Class Object: public Superobject {...} 

在派生類B我要填寫成員字段vecObject類型的對象。如果超類沒有使用指針,我會遇到對象分片的問題。因此,在類B構造函數中,我想初始化vec作爲Object*類型的指針向量。

EDIT2

是的,在我看來,動態分配是合理的選擇和使用數組的想法是一個壞主意。當數組超出範圍時,事情就會出錯,因爲向量中的指針指向不再包含對象的內存位置。

在構造函數中的B類我

B(int n) { 
    vector<Object*> vec; 
    Object ar[n]; 

    for(int id=0; id<n; id++) { 
     ar[id] = Object(id); 
    } 

    for(int id=0; id<n; id++) { 
     v.push_back(ar+id); 
    } 
} 

這引起了非常奇怪的行爲,在B類的對象

+2

如果你不想動態內存分配,那麼你爲什麼使用指針?你也可以使用Object數組。 –

+1

爲什麼你想在第一個地方存儲指針? – Yuushi

+1

第二種方法的問題在於它不是合法的C++。 '對象ar [n];'不合法,除非n是常量。另外,根據你的編輯,你有一個類層次結構,但有'Object ar [n];'你只有對象,而不是超級對象。順便說一句,你的第一種方法也是錯誤的,因爲你正在存儲已被銷燬的對象的地址。我只會使用動態內存分配。 – john

回答

6

在這個循環中:

for(int id=0; id<n; id++) { 
    Object ob = Object(id); 
    v.push_back(&ob); 
} 

你正在創建n次堆棧對象實例。每次迭代都會創建並移除元素。你可以簡單地避免這種情況使用:

for(int id=0; id<n; id++) { 
    Object* ob = new Object(id); 
    v.push_back(ob); 
} 

感謝每一個新的元素堆存在不是在棧中。嘗試添加到Object類的構造類似的東西:

std::cout<<"Object ctor()\n"; 

,並在析構函數相同:

std::cout<<"Object dtor()\n"; 

如果你不想創建一個「新」的嘗試@寫的原因,這些對象woolstar

+0

+1注意到錯誤 – Pat

3

沒有出現在你的版本沒有內存泄漏。當程序離開你的作用域時,矢量以及數組被銷燬。對於第二個問題:爲什麼不直接將對象直接存儲在向量中?

vector<Object> v; 

for(int i = 0; i < n; i++) 
{ 
    Object obj = Object(i); 
    v.push_back(obj); 
} 
5

你對內存泄漏的問題讓我覺得你擔心這些對象的生命週期和清理。我最初提議shared_ptr包裝,但C++ 11給了我們unique_ptr,而C++ 14填補了缺少的make_unique。因此,所有我們可以做:

vector<unique_ptr<SuperObject>> v ; 
你在完美的轉發和可變參數模板的其中的美妙場所創建

v.push_back(make_unique<Object>(...)) ; 

是你不得不忍受一些堆分配,但當v消失時,一切都將被清除。

有人提出了一個助推庫,ptr_container,但這不僅需要增加您的項目,但教育所有未來的讀者這是什麼ptr_container是。

+3

請除非你需要shared_ptr語義,否則不要這樣做。只需使用http://www.boost.org/doc/libs/1_55_0/libs/ptr_container/doc/ptr_container.html。 – KitsuneYMG