2010-11-09 18 views
1

我有一個向量與原始指針(不,我不能使用智能指針),我想添加項目列表中的for循環。我做了一個小試驗項目,我想知道在指針管理方面這是否被認爲是很好的C++代碼。這會被認爲是好的C++代碼

請僅考慮原始指針管理,我對這個特定問題的智能指針不感興趣,我試圖解決這個問題。

一個簡單的對象:

class Request 
{ 
public: 
    std::string name; 

}; 

std::vector<Request*> requests; 

for (int i = 0; i < 5; i++) 
{ 
    std::stringstream ss; 
    ss << "elemenent "; 
    ss << i; 

    std::string s = ss.str(); 

    Request* req = new Request(); 
    req->name = s; 

    requests.push_back(req); 

} 

編輯:

所以我試圖解決從this庫中添加的DOMNode *的向量的問題。
我開始覺得試圖從我的項目庫中爲我需要的零件編寫一個包裝,這是一個壞主意。或者,也許圖書館不好? 我沒有得到它使用smart_ptr正常工作,如果有人有,那麼我想聽聽它。

+0

如果你不使用智能指針那麼這一切都取決於你打算如何清理這些請求。如果這是我們的評論,我還建議使用構造函數來初始化請求名稱。 – 2010-11-09 09:53:27

+2

這是真的不清楚你要求什麼。這段代碼中沒有指針管理。您正在堆上創建一些對象,然後從不刪除它們。 – 2010-11-09 09:54:24

+0

這真的很簡單,我正在使用只使用指針的庫,沒有對象具有拷貝構造函數。我需要將這些對象中的一些添加到列表中,我想知道正確的方法是什麼。 – 2010-11-09 09:59:19

回答

5

好吧,這會泄漏內存,所以它很糟糕。你能使用Pointer Container嗎?

此代碼泄漏的原因是因爲您使用new在堆上創建對象,但您從未對其調用delete

至於你的評論,如果你有一個手動管理一些資源的對象,你需要The Big Three

+0

太棒了,我懷疑我是在泄漏......如果請求只有一個私人副本幷包含指針成員,該怎麼辦? – 2010-11-09 09:54:37

+0

+1或智能指針的容器(boost :: shared_ptr或std :: tr1 :: smart_ptr)。 – Klaim 2010-11-09 09:54:51

+0

@Tony:爲您的評論添加了信息。 – 2010-11-09 09:56:50

-1

快速改善可能是從std::vector<Request*>派生類RequestVector,添加一個ClearRequests方法(刪除所有Request對象並清除向量),並做出它的析構函數調用ClearRequests。 (實際上彙總RequestVector中的向量可能是更好的選擇,但派生類更快完成)。

+2

-1:[不鼓勵繼承STL-Containers](http://stackoverflow.com/questions/2034916/is-it-okay-to-inherit-implementation-from-stl-containers-rather-than-delegate) 。你應該使用你的建議組合。 – 2010-11-09 10:19:36

+0

我喜歡從STL容器繼承。如果你沒有傳遞指向基類的指針,這是絕對安全的,在99.9%的情況下你甚至不會考慮這樣做。你多久存一次指向容器的指針?有多少次你會考慮使用指向基類的指針?無論如何你的容器在堆上多久一次?他們絕大部分都在堆棧或成員數據上。這是FUD。 – 2010-11-09 10:45:38

0

如果您不能(或允許)使用智能指針,也許你可以使用一個簡單的內存管理這樣的:

template <class T> 
class MemManager 
{ 
public: 
    typedef std::vector<T*> Vec; 
    ~MemManager() 
    { 
    size_t sz = v_.size(); 
    for (size_t i = 0; i < sz; ++i) 
     delete v_[i]; 
    } 
    T* pushNewObject() 
    { 
    T* t = NULL; 
    try 
    { 
     t = new T; 
     if (t != NULL) 
      v_.push_back(t);    
    } 
    catch (std::bad_alloc& ex) { /* handle ex */ } 
    return t; 
    } 
    const Vec& objects() const { return v_; } 
private: 
    Vec v_; 
}; 

// test 
{ 
    MemManager<Request> mm; 
    for (int i = 0; i < 5; i++) 
    { 
     std::stringstream ss; 
     ss << "elemenent "; 
     ss << i; 

     std::string s = ss.str(); 

     Request* req = mm.pushNewObject(); 
     req->name = s;  
    } 
} // all Request objects will be deleted here when 
    // the MemManager object goes out of scope. 
+0

這也泄漏了。 (請閱讀Big Three並考慮異常安全) – 2010-11-09 10:39:19

+0

@Matthieu您能解釋一下這個泄漏的方式/位置嗎? – 2010-11-10 05:11:46

+0

@Vijay:如果'push_back'失敗會發生什麼?不可否認,它應該只是因爲std :: bad_alloc而發生的,這意味着你內存不足,或者簡單地說'vector'已經增長太多了,並且不再有足夠大小的塊被發現。 'MemManager'也是可複製的問題,你應該禁止複製和分配。最後,在接口說明上:'newObject'有什麼意義?我會說要麼讓用戶處理內存(隱藏'新'不給太多),要麼提供一個完整的包裝,將分配和註冊對象在同一時間:) – 2010-11-10 07:41:16

0

我會考慮你有一個循環,在方法的結尾,以調用刪除vector的每個成員。

仍然存在問題,特別是異常安全問題。

  • 如果有任何創建Request和其在vector登記之間的罰球,你已經失去了記憶。一種解決方案是暫時使用scoped_ptr來保存內存,push_backptr.get(),然後調用release方法,因爲現在內存歸vector所有。
  • 如果在創建vector中的項目和摧毀它們之間的點之間有任何內容出現,則需要捕捉異常,銷燬項目,然後重新拋出。

有可能是其他人,但RAII已被髮明的原因,這是真的很難做到沒有(正確...)

0

如果您不能使用智能指針,請使用boost::ptr_vector

請注意,如果您使用的是TinyXml,在XmlNode內存管理可能是由圖書館決定 - 最近的歷史IIRC的是,你的很多問題都與正確理解記憶的所有權和發行範例這個庫相關聯。

What memory management do I need to cleanup when using TinyXml for C++?

What is the best open XML parser for C++?

+0

使用Xerces ......這更難以理解我在找... – 2010-11-10 09:46:05

相關問題