我有这种结构并动态分配数组。 我不能使用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 * date,street,city。
现在,我需要删除这些内存块。 好吧,我试过这个:(班上的析构函数) 问题是:我应该如何正确释放所有分配的内存?
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;
答案 0 :(得分:4)
我不会试图解决这段代码中的每一个问题,而是告诉你一个原则,因为某些原因从未在编程课程中教过:从小而简单开始,一次增加一点复杂性,测试时间每一步,永远不会添加到不起作用的代码。
看看这个:
arr[counter]->moves[0]->city=new char[strlen(city)+1];
arr[counter]->moves[0]->city=city;
即使假设已正确构造此Moves,您使用new
分配内存,然后立即放弃它,导致内存泄漏。然后 if { {1}}(一个与成员同名的变量,不是一个好主意)是指向堆上city
的指针,如果没有用{{{ 1}}在其生命周期的剩余时间内,如果没有其他指向该数组的指针(或者至少没有用这样的指针做任何不好),那么这不会导致未定义的行为。你觉得这很幸运吗?
相反,请考虑一下:
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
。
答案 1 :(得分:0)
这篇文章很难回答,但这里有一些建议:
std::vector
代替数组std::string
而不是const char * struct Moves
和struct 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 ++): - )
答案 2 :(得分: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很好,有帮助你,你应该使用它。