结构体中指针数组的析构函数

Destructor of arrays of pointers in structures

本文关键字:析构函数 数组 指针 结构体      更新时间:2023-10-16

我有这个结构和动态分配的数组。我不能使用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;
};

我有一个类,在那里我创建了一个指针数组结构数据,我动态分配char*日期,街道,城市。

现在,我需要删除这些内存块。嗯,我试过了:(我的类的析构函数)问题是:我应该如何正确释放所有分配的内存?

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;

与其试图解决这段代码中的每个问题,不如告诉你一个编程课程中从未教过的原则:从小而简单的开始,每次增加一点复杂性,每一步都进行测试,永远不要添加不起作用的代码

看这个:

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

即使假设这个Moves已经正确构造,您使用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[]了。

这篇文章很难回答,但这里有一些建议:

  • 考虑使用std::vector代替数组
  • 考虑使用std::string代替const char *
  • 考虑将struct Movesstruct Data成员的销毁纳入这些定义
例如:

struct Moves
{
    const char* date;
    const char* street;
    const char* city;
    ~Moves () {
      delete [] date;
      ...
    }
};

这是你的class Reg使用std::vector来保存类型为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
};

好的c++参考是cplusplus.com。

如果你加强你的问题,你会得到一些好的答案(并学到很多c++):-)

这有多好?

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很好,可以帮助你,你应该使用它