2010-07-18 33 views
0

好的,你們對我最後一個問題非常有幫助,所以我會再試一次。這也是作業,雖然最後一個已經很老了,但已經提交併正在等待標記。所以如果有什麼會咬我的話,那可能就是這個問題。我已經混淆了類名等,因爲它仍然可以提交作業(對於其他學生)。istream_iterator泄漏內存

我有一個類,其唯一成員是一個指向對象的指針。這個類被構造爲暴露它當前持有的指針的某些操作 - Object *o_,它是一個基類到Object{1, 2, 3, ...}。現在,我可以在沒有任何內存泄漏或崩潰的情況下執行以下操作。

std::vector<ObjectPtr> v; 
v.push_back(ObjectPtr(new Object1(..., ..., ...))); 
v.push_back(ObjectPtr(new Object2(..., ...))); 
v.push_back(ObjectPtr(new Object1(.., .., ..))); 

// Copy Constructor Ptr 
std::vector<ObjectPtr> v2(v); 
// Assignment Operator Ptr 
std::vector<ObjectPtr> v3; 
v3 = v2; 

所有這些工作,並沒有內存泄漏。但是,如果我嘗試從istream_iterator<ObjectPtr>的文件中讀取內容,它會開始泄漏。 ObjectPtr是處理動態內存的唯一類,並且Object *o_要麼被設置爲NULL,要麼被Object{1, 2, 3, ...}分配。

該文件被讀看起來像這樣

 
Object1 
... 
... 
Object2 
... 
... 
Object1 
.. 
std::ifstream is("file.txt"); 
std::istream_iterator<ObjectPtr> in(is), end; 
for (; in != end; ++in) 
    cout << *in << "\n"; 

使用這些值來讀取ObjectPtr友元函數看起來像

friend istream &operator>>(istream &is, ObjectPtr &op) { 
    std::string tmp; 
    while (std::getline(is, tmp)) { 
     if (tmp == "Object1") { 
      op.o_ = new Object1; 
      return is >> (Object1 &)*(op.o_); // Send it to operator>> for Object1 
     } 
     if (tmp == "Object2") { 
      op.o_ = new Object2; 
      return is >> (Object2 &)*(op.o_); 
     } 
     ... 
    } 
    return is; 
} 

某處這裏開始unicorning我,我真的很想知道爲什麼。

簡而言之 - 當賦值和複製構造函數正常工作時,istream_iterator會泄漏內存,這導致我相信類Object{1, 2, 3, 4, ..}構造正確,並且問題將在operator>>中找到。

回答

2

這是我第一件事。我不知道這是否是你獵殺的問題:

friend istream &operator>>(istream &is, ObjectPtr &op) { 
    std::string tmp; 
    while (std::getline(is, tmp)) { 
     if (tmp == "Object1") { 
      op.o_ = new Object1; 

在最後一行,幹什麼去了?op.o舊值?請記住,流入對象意味着流入完全構造的對象,並且必須介意對象的舊數據。 (這就是爲什麼往往喜歡構造採取std::istream。對於複雜的對象保險櫃一個對象,它是在非常下一刻改變初始化。)

是否ObjectPtr賦值操作符或swap()成員函數?如果是這樣,通過構建一個新對象並將其分配給op來交換它可能更容易實現輸入操作符。

+0

哦,夥計..你讓我的一天 - 刪除op.o_;謝謝你,謝謝你,謝謝你! – citizencane 2010-07-18 19:49:12

+0

@citizencane:請注意,您還需要在其他許多地方留意該「o」成員。什麼是分配?複製建設?真的,我寧願用其他成員的方式來實現'operator >>()'(比如我在我的答案中寫的),而不是手動複製所有代碼來動態分配對象。 – sbi 2010-07-18 19:54:23

+0

再次考慮這個問題,我甚至會把ObjectPtr分成兩個類,因爲它至少做了兩件事:(A)它管理一個動態分配的對象,(B)它作爲代理處理這個目的。如果將(A)分離成適合的智能指針類,則實現(B)變得更加容易和更清晰。 – sbi 2010-07-18 19:56:22