2013-03-31 31 views
3

我想問一個普遍的建議。下面的代碼完全編譯並粗略地表示我處理的代碼的結構。 簡而言之,我想將從基類(Class1)派生的一系列對象和其他一些參數從一個地方傳遞到另一個地方。更確切地說,實現父類的不同子類,收集這些類的實例並傳遞給參數進行處理。std ::要傳遞對象的對象/指針/智能指針的向量(buss error:10)?

問題是,你會推薦使用一個對象的向量或向量指針?我不介意從C++11std::unique_ptr,std::shared_ptr),如果這是一些新的東西去更好/更安全/更少的內存泄漏/等出於某種原因。我真的很感激,如果有人能夠爲這種情況提供建議的容器和/或提供一個使用C++11的例子。

p/s/here UncleBens表示,如果/當拋出異常時,使用指針可能導致內存泄漏。所以也許我應該真的使用智能指針來完成任務?這看起來如何?

P/P/S /有趣的是,現實生活中的例子給我總線錯誤:10當我嘗試使用這些Class2對象從std::vector< Container<d>*>/std::vector< Container<d>>。不過,我無法重現錯誤在簡單的情況下...

#include <string> 
#include <iostream> 
#include <vector> 


template<int dim> 
class Class1 { 
    public: 

    Class1() {}; 
    ~Class1() {}; 

}; 

template<int dim> 
class Class2 : public Class1<dim> 
{ 
    public: 
    Class2() : 
     Class1<dim>() {}; 

}; 

template <int dim> 
class Container 
{ 
    public: 
    Container(Class1<dim> & f, int param1) : c1(f), param_(param1) {} 

    Class1<dim> & c1; 
     int param_; 
}; 

static const int d = 2; 

int main() 
{ 
    int p = 1; 
    Class2<d> c2; 
    std::vector< Container<d> *> p_list; 
    std::vector< Container<d> > list; 
    { 
     p_list.push_back (new Container<d> (c2,p)); 
    } 
    std::cout<<"from pointers: "<<p_list[0]->param_<<std::endl; 

    { 
     list.push_back(Container<d> (c2,p)); 
    } 
    std::cout<<"from objects: "<<list[0].param_<<std::endl; 
} 

回答

0

首先,Class 1的析構函數應標明虛擬的,否則當一個派生類的一個實例(等級2舉例)被破壞,它的析構函數不會被正確調用。

至於你的問題,使用對象的容器的後果是:

  • 的容器可能需要使對象的副本,所以你需要確保有一個拷貝構造函數(類在該示例中獲取由編譯器生成的默認值)。複製對象可能會對性能產生影響,因此您需要正確定義副本的語義(深層或淺層,即創建class1對象的新副本,還是僅複製引用)。
  • 您不能有任何多態性,因此您無法繼承Container的子類,然後將基類和子類的實例放在同一個容器中。
  • 根據容器的不同,您的對象在內存中會是連續的(對於矢量來說就是這種情況),這可以帶來性能方面的好處。

如果您使用原始指針的容器,那麼容器只需要複製指針(更快),並且可以添加所包含類型的派生實例。缺點是你必須在使用後手動銷燬對象,並且正如你所提到的那樣,很容易泄漏內存。

shared_ptrs對原始指針有類似的好處/缺點,但關鍵的好處是shared_ptr在沒有任何東西引用它時會爲你破壞對象,這使得你不太可能引入內存泄漏(但它是在涉及例外時仍然不可能這樣做)。

鑑於您將這些對象交給進一步處理,我會說基於shared_ptr的方法是一個不錯的選擇。在以上這些原始指針的使用共享的師生比的後果是:

  • 可以有一個性能開銷,爲了是線程安全的,最shared_ptr的實現需要檢查/套鎖(這可能涉及系統調用OS)。
  • 您仍然可以通過在對象之間引入循環引用來泄漏內存。
  • 你將不得不使用一個實現C++ 11的編譯器或使用外部庫(大多數人使用boost)。

使用shared_ptrs的例子看起來像這樣(未測試)。

#include <string> 
#include <iostream> 
#include <vector> 

template<int dim> 
class Class1 { 
    public: 
     Class1() {}; 
     virtual ~Class1() {}; 

}; 

template<int dim> 
class Class2 : public Class1<dim> 
{ 
    public: 
     Class2() : 
     Class1<dim>() {}; 

}; 

template <int dim> 
class Container 
{ 
    public: 
     Container(boost::shared_ptr<Class1<dim>> f, int param1) : c1(f), param_(param1) {} 

     boost::shared_ptr<Class1<dim>> c1; 
     int param_; 
}; 

static const int d = 2; 

int main() 
{ 
    int p = 1; 
    boost::shared_ptr<Class1<d>> c2 = boost::make_shared<Class2<d>>(); 

    std::vector<boost::shared_ptr<Container<d>>> list; 
    list.push_back(boost::make_shared<Container<d>>(c2,p)); 

    std::cout << "from objects: " << list[0]->param_ << std::endl; 
} 

總之,如果代碼接收容器不會存儲裁判給他們的任何地方,而且你不需要多態,那麼對象的容器可能是好的。如果需要接收容器的代碼將它們存儲在某處,並且/或者您想要多態容器,則使用共享的ptrs。

+0

非常感謝您的詳細解答。將我的真實代碼改寫爲共享指針... – Denis

+0

注意到您沒有在您的答案中定義「list」。我想這是'std :: vector',或者更好'boost :: shared_ptr >'? – Denis

+0

哎呀,是的,我錯過了。我已經更新了添加列表聲明的答案,它是共享ptrs的std :: vector。 –