Reputation: 1
I have this structures and dynamically allocated arrays. I can't use std::vector and std::string, because it is homework.
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 have a class, where I create a array of pointers on structure Data, where I dynamically allocate char* date, street, city.
Now, I need to delete these blocks of memory. Well, I've tried this: ( Destructor of my class) Question is: how should I free all allocated memory correctly?
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;
}
Here is an example of allocating:
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;
Upvotes: 0
Views: 1890
Reputation: 99104
Rather than try to address every problem in this code, I'll tell you a principle that for some reason is never taught in programming courses: Start small and simple, add complexity a little at a time, test at every step and never add to code that doesn't work.
Look at this:
arr[counter]->moves[0]->city=new char[strlen(city)+1];
arr[counter]->moves[0]->city=city;
Even assuming that this Moves has been correctly constructed, you allocate memory with new
and then immediately abandon it, causing a memory leak. Then if city
(a variable with the same name as a member, not a good idea) is a pointer to a char[]
on the heap, and if nothing bad is done with city
for the rest of its lifetime, and if no other pointer to that array exists (or at least nothing bad is done with such a pointer) then this will not lead to undefined behavior. Do you feel that lucky?
Instead, consider this:
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);
Note that once setCity()
is working correctly, invoking it from outside is clean, safe and simple. And once Moves
is set up correctly, Data
can be rewritten in a similar fashion, and then Reg
.
And once you're used to this approach, you can learn to use std::string
, and never muck around with char[]
again.
Upvotes: 4
Reputation: 18848
How much nicer is this?
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;
};
Now you can add new Moves
and they will be released on destruction of the Data
object.
int main()
{
Data d;
d.moves.push_back(Data::MovesPtr(new Moves()));
return 0;
}
The STL is nice, is there to help you, and you should use it.
Upvotes: 0
Reputation: 2389
It's hard to answer this post, but here are a few suggestions:
std::vector
instead of arraysstd::string
instead of const char *struct Moves
and struct Data
within those definitionsFor example:
struct Moves
{
const char* date;
const char* street;
const char* city;
~Moves () {
delete [] date;
...
}
};
Here's your class Reg
using a std::vector
to hold objects of type 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
};
A good C++ reference is cplusplus.com.
If you enhance your question you'll get some good answers (and learn a lot of C++) :-)
Upvotes: 1