2013-04-10 54 views
0

我有這種結構和動態分配的數組。 我不能使用std :: vector和std :: string,因爲它是作業。結構體中指針數組的析構函數

struct Moves 
    { 
     const char* date; 
     const char* street; 
     const char* city; 
    }; 

struct Data 
{ 
    const char* id; 
    const char* name; 
    const char* surname; 
    int count; 
    Moves** moves; 

}; 

我有一個類,其中I創建結構數據,其中I動態地分配字符*日期,街道,城市指針的陣列。

現在,我需要刪除這些內存塊。 嗯,我已經試過這個:(我的類的析構函數) 問題是:我應該如何正確釋放所有分配的內存?

class Reg 
{ 
private: 
Data** arr; 
int counter; 
public: 
    Reg(){ arr=new Data*[1000]; } 
    ~Reg(); 
    ... other methods 
}; 

Reg::~Reg() 
    { 
     for(int i=0;i<counter;i++) 
     { 
      for(int c=0;c<arr[i]->count;c++) 
      { 
       delete arr[i]->moves; 
      } 

      delete arr[i]; 
     } 

     delete [] arr; 
    } 

下面是分配的一個例子:

arr[counter]=new Data; 
arr[counter]->id=new char[12]; 
arr[counter]->id=id; 
arr[counter]->name=new char[strlen(name)+1]; 
arr[counter]->name=name; 
arr[counter]->surname=new char[strlen(surname)+1]; 
arr[counter]->surname=surname; 

arr[counter]->moves=new Moves*[100]; 
arr[counter]->moves[0]=new TMoves; 

arr[counter]->moves[0]->city=new char[strlen(city)+1]; 
arr[counter]->moves[0]->city=city; 

arr[counter]->moves[0]->date=new char[strlen(date)+1]; 
arr[counter]->moves[0]->date=date; 

arr[counter]->moves[0]->street=new char[strlen(street)+1]; 
arr[counter]->moves[0]->street=street; 
+3

問題是什麼? – 2013-04-10 23:12:30

+0

arr是int嗎?不是int數組? – taocp 2013-04-10 23:12:49

+4

給每個結構自己的析構函數('Data()','〜Moves')並讓他們自己照顧會更好。 – Beta 2013-04-10 23:15:10

回答

0

這是很難回答這個職位,但這裏有幾個建議:

  • 使用std::vector代替陣列的考慮
  • 考慮使用std::string而不是const char *
  • 考慮將的struct Movesstruct Data成員破壞這些定義

內。例如:

class Reg 
{ 
    private: 
    std::vector<Data*> arr; 
    int counter; // this can probably be removed 
    public: 
    Reg() 
     :arr(1000, NULL) // initialize arr with 1000 NULL raw pointers 
    { 
    } 

    ~Reg(); 
    ... other methods 
}; 

struct Moves 
{ 
    const char* date; 
    const char* street; 
    const char* city; 

    ~Moves() { 
     delete [] date; 
     ... 
    } 

}; 

class Reg使用std::vector持有Data *類型的對象這裏的

一個好的C++參考是cplusplus.com

如果你提高你的問題,你會得到一些很好的答案(和學習了很多C++的):-)

+0

我試過這個,但valgrind說: 無效的免費()/刪除/刪除[]/realloc() – cplusplusnewbie 2013-04-10 23:29:58

+0

剛剛閱讀您的更新;如果你不能使用矢量/字符串,那麼我的第一個問題是:「分配」示例是否爲你編譯?我懷疑這行:'arr [counter] - > id = id;' – Tom 2013-04-10 23:48:28

0

如何更漂亮是這樣嗎?現在

struct Moves 
{ 
    std::string date; 
    std::string street; 
    std::string city; 
}; 

struct Data 
{ 
    Data() { moves.reserve(1000); } 
    std::string id; 
    std::string name; 
    std::string surname; 

    typedef std::unique_ptr<Moves> MovesPtr; 
    typedef std::vector<MovesPtr> MovesList; 
    MovesList moves; 
}; 

您可以添加新的Moves,他們將在Data對象的破壞被釋放。

int main() 
{ 
    Data d; 
    d.moves.push_back(Data::MovesPtr(new Moves())); 

    return 0; 
}  

STL很好,有幫助你,你應該使用它。

4

與其試圖解決代碼中的每個問題,我都會告訴你一個原則,即由於某種原因,從未在編程課程中教過:從小而簡單的開始,每次增加一點複雜度,步驟和絕不會添加到不起作用的代碼。

看看這個:

arr[counter]->moves[0]->city=new char[strlen(city)+1]; 
arr[counter]->moves[0]->city=city; 

即使假設此招式已經正確構建,new分配內存,然後立即放棄它,從而導致內存泄漏。然後如果city(具有相同名稱的一員,不是一個好主意變量)是指向在堆上一個char[],並且如果沒什麼不好與city完成其生命週期的休息, 如果沒有其他指向該數組的指針(或者至少沒有使用這樣的指針完成任何錯誤),那麼這不會導致未定義的行爲。你覺得幸運嗎?

相反,考慮一下:

struct Moves 
{ 
private: 
    const char* city; 

public: 

    Moves() 
    { 
    city = NULL; 
    } 

    ~Moves() 
    { 
    if(city) 
     delete [] city; 
    } 

    void setCity(const char ncity[]) 
    { 
    if(city) 
     delete [] city; 
    char *temp = new char[strlen(ncity)+1]; 
    strcpy(temp, ncity); 
    city = temp; 
    } 
}; 

... 
arr[counter]->moves[0]->setCity(someCity); 

注意,一旦setCity()從外面工作正常,調用它是清潔,安全,簡單。並且一旦Moves設置正確,Data可以用類似的方式重寫,然後Reg

而且一旦你習慣了這種方法,你可以學習使用std::string,並且再也不會使用char[]

+0

謝謝,這幫了我:) – cplusplusnewbie 2013-04-11 18:57:33