2013-02-08 102 views
1

我有一個相當簡單的問題,但無法將其包裹在頭上。在堆和堆棧上創建混合矢量對象

考慮我有這樣的代碼:

#include <iostream> 
#include <vector> 
using namespace std; 

class B 
{ 
public: 
    B(const int& val) {this->val = val;} 
    int val; 
}; 

class A 
{ 
public: 
    A() {} 
    void Set(B& ptb) 
    { 
     ptBs.push_back(&ptb); 
    } 
    void Set(const int& val) 
    { 
     ptBs.push_back(new B(val)); 
    } 
    std::vector<B*> ptBs; 
}; 

int main() 
{ 
    A* ptA = new A(); 
    ptA->Set(B(10)); 
    ptA->Set(38); 

    for (int i=0; i<ptA->ptBs.size(); i++) 
     cout << ptA->ptBs[i]->val << endl; 

    delete ptA; 

    system("pause"); 
    return 0; 
} 

輸出結果是:

10 
38 

但我認爲有內存泄漏是怎麼回事在void Set(const int& val),如果我不會打電話與數組中刪除元素,由此方法創建。

我怎麼能說,這的std ::向量已經在堆上創建的元素,所以我可以在〜A()析構函數像這樣釋放內存:

~A() 
{ 
    for (int i=0; i<ptBs.size(); i++) 
     delete ptBs[i]; 
} 

,做我必須刪除矢量元素,是否通過臨時性的新操作呼叫創建?

也許我在這裏看不到很簡單的東西,但我真的需要在我的應用程序中使用此功能。

PS。 10和38只是一個簡單的例子。使用不同的參數可以調用數千次函數來調用函數Set

+0

這不是一個解構,它的析構函數。 – bash0r 2013-02-08 13:57:16

+0

你可以使用'std :: pair '來表示哪些元素是堆分配的。在析構函數中,您可以執行'if(ptBs [i] .first)delete ptBs [i] .second;' – bash0r 2013-02-08 14:00:52

+1

讓您的生活變得簡單 - 選擇一個或另一個。 – 2013-02-08 14:18:00

回答

3

幸運的是,這條線將不編譯:

ptA->Set(B(10)); 

這是因爲B(10)是它創建了一個prvalue臨時B類型的構造轉換表達式;一個前值不能綁定到左值引用B &參數void A::Set(B& ptb)。這是C++語言保護您免受將懸掛指針存儲爲臨時值的後果。

通常更有意義的A按值來存儲它的B項目:

std::vector<B> Bs; 
+0

那麼我提供的代碼是完全正常工作和編譯。但是,我決定將對象存儲在數組中,而不是指針。謝謝。 – GuardianX 2013-02-08 16:39:39

2

您應該決定是否將B類型的對象的所有權轉讓給A的實例。混合使用不會導致任何問題。試想一下,記錄這個類:this class may or may not take ownership to the objects it holds.

,我不建議另一種方法是創建一個包裝,以指針B,這需要一個指向B和一個布爾標誌在它的構造函數和布爾標誌將指示指針是分配給棧上的對象還是分配給堆上的對象。