2013-04-10 102 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