【问题标题】:Destructor of arrays of pointers in structures结构中指针数组的析构函数
【发布时间】:2013-04-03 00:25:59
【问题描述】:

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

};

我有一个类,我在结构 Data 上创建一个指针数组,我在其中动态分配 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 是 int 吗?不是 int 数组?
  • 最好给每个结构体自己的析构函数(Data()~Moves),让它们自己处理。
  • @Beta 你能把你的代码贴在这里吗?
  • 停止使用指针,使用标准容器

标签: c++ arrays pointers structure


【解决方案1】:

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

  • 考虑使用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++):-)

【讨论】:

  • 我试过了,但是 valgrind 说:无效的 free() / delete / delete[] / realloc()
  • 只需阅读您的更新;如果您不能使用向量/字符串,那么我的第一个问题是:“分配”示例是否为您编译?我怀疑这条线:arr[counter]-&gt;id=id;
【解决方案2】:

这有多好?

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

【讨论】:

    【解决方案3】:

    与其试图解决这段代码中的每一个问题,我会告诉你一个由于某种原因在编程课程中从未教授过的原则:从小而简单开始,一次增加一点复杂性,在每一步,永远不要添加到不起作用的代码中。

    看看这个:

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

    即使假设这个 Move 已经正确构造,你用 new 分配内存然后立即放弃它,导致内存泄漏。 然后 如果 city (与成员同名的变量,不是一个好主意)是指向堆上 char[] 的指针,并且 if 没有对 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[]了。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-04-21
      • 2019-06-20
      • 2013-10-19
      • 2018-01-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多