2010-10-18 62 views
1

我有一個方法創建了一些Foo並將它添加到Foos的矢量中。 Foos負責在銷燬期間刪除他們的酒吧。 Foo構造函數需要一個Bars的指針和它們的大小。當函數返回時,本地Foo被刪除並銷燬它的Bars,但是我得到一個有效的Foo對象。C++用局部變量指針管理

我應該如何更正確地處理這個問題?我應該用其他方式管理酒吧嗎?我應該讓構造函數複製數組嗎?我可能會有成千上萬的酒吧。

還沒有試圖編譯這個,這只是一個發生了什麼事情的例子。

class Bar 
{ 
    public: 
     Bar(){} 
     ~Bar(){} 

     int a; 
     int b; 
     int c; 
}; 

class Foo 
{ 
    private: 
     Bar * myBars; 
     int size; 

    public: 
     Foo(Bar * myBars, int size) 
     { 
      this->myBars = myBars; 
      this->size = size; 
     } 

     Bar * getBars() 
     { 
      return myBars; 
     } 

     int getSize() 
     { 
      return size; 
     } 

     ~Foo() 
     { 
      if(myBars != NULL) 
      { 
       if(size == 1) 
       { 
        delete myBars; 
       } 
       else if(size > 1) 
       { 
        delete [] myBars; 
       } 
      } 
     } 
}; 

void doIt(std::vector<Foo> & foos) 
{ 
    Bar * myBars = new Bar[4]; 
    //Pretend we initialize the Bars... 
    Foo foo(myBars); 
    foos.push_back(foo); 

    //local foo gets deleted 
} 

int main() 
{ 
    std::vector<Foo> foos; 
    doIt(foos); 

    Bar * myBars = foos[0].getBars(); 
    int size = foos[0].getSize(); 

    //Do something with myBars 

    return 0; 
} 
+0

大小並不是一個很好的指示符,因爲您可以像這個新的Bar [1]那樣分配,而且必須使用delete []刪除它,否則是否使用delete []或delete。因此,使用布爾值來指示數組分配,或者甚至更好地傳遞一個函數,它將執行正確的操作,或者使用知道如何刪除它的智能指針。 – 2010-10-18 17:17:02

回答

0

類似酒吧,你可以創建富也反對在堆上,以避免在doIt方法functon破壞。如果Foo對象是動態分配的,它將不會在doIt()函數返回時被銷燬。

您可以像下面(工作代碼)結束清理所有Foo和Bar對象

#include <vector> 
using namespace std; 
class Bar 
{ 
    public: 
     Bar(){} 
     ~Bar(){} 

     int a; 
     int b; 
     int c; 
}; 

class Foo 
{ 
    private: 
     Bar * myBars; 
     int size; 

    public: 
     Foo(Bar * myBars, int size) 
     { 
      this->myBars = myBars; 
      this->size = size; 
     } 

     Bar * getBars() 
     { 
      return myBars; 
     } 

     int getSize() 
     { 
      return size; 
     } 

     ~Foo() 
     { 
      if(myBars != NULL) 
      { 
       if(size == 1) 
       { 
        delete myBars; 
       } 
       else if(size > 1) 
       { 
        delete [] myBars; 
       } 
      } 
     } 
}; 

void doIt(std::vector<Foo *> & foos) 
{ 
    Bar * myBars = new Bar[4]; 
    //Pretend we initialize the Bars... 
    Foo *pFoo = new Foo(myBars, 4); 
    foos.push_back(pFoo); 
} 

int main() 
{ 
    std::vector<Foo *> foos; 
    doIt(foos); 

    Bar * myBars = foos[0]->getBars(); 
    int size = foos[0]->getSize(); 

    for(int i = 0;i < foos.size(); i++) 
    { 
     delete foos[i]; 
    } 
    foos.clear(); 

    return 0; 
} 
+0

我喜歡std :: auto_ptr,但它不適用於標準容器。此外,代碼並不是特例安全的。如果你打算擁有一個擁有指針的容器,那麼你應該看看boost指針容器。 boost :: ptr_vector 2010-10-18 16:25:15

+0

@Martin:已更新。 – bjskishore123 2010-10-18 16:28:41

1

爲什麼不使用std::vectorBar S:

class Foo 
{ 
    private: 
     vector<Bar> myBars; 

    public: 
     Foo(const vector<Bar>& bars) : myBars(bars) {} 

     vector<Bar>& getBars() 
     { 
      return myBars; 
     } 

     int getSize() 
     { 
      return myBars.size(); 
     } 
}; 
+0

比我的好主意。我在想什麼。 – 2010-10-18 20:20:47

+0

@馬丁,謝謝。 – Donotalo 2010-10-19 01:51:53

0

你不顯示拷貝構造函數,並且沒有合適的默認拷貝構造函數。 您也沒有stl容器經常需要的默認(無參數)構造函數。

當您將Foo推入矢量中時,它將創建一個新的Foo作爲副本。

目前您可能會刪除酒吧指針兩次。

本機數組應避免使用非POD類型 - Bar[4]不會在每個對象的Bar上運行構造函數。優先使用Vector

+0

是的,它正在刪除Bar指針兩次。 – bjskishore123 2010-10-18 16:39:05

+0

我意識到發生了什麼,我正在尋找最好的方法(tm)來解決它。 – foobar1234 2010-10-18 18:05:58

+1

@ foobar1234:推薦閱讀一些書,比如Meyers Effective C++,Sutter Exceptional C++。沒有關於所有Foo和Bar的總體結構和用法的更多細節,「最佳方式」(tm)將不清楚。例如,你會一直'爲每個'的容器,或需要查找,需要添加和/或刪除許多項目等。 – 2010-10-18 18:18:07