i have the following struct:
struct Message {
Agent *_agent;
double _val;
};
and the following Ptrs array:
typedef Message* MessageP;
MessageP *_msgArr;
_msgArr = new MessageP[MAX_MESSAGES];
this is the method that inserts a Message to the array:开发者_如何学编程
void Timing::AddMessage(Agent * const agentPtr, double val) {
MessageP msgPtr = new Message;
assert(msgPtr != 0);
//assign values:
(*msgPtr)._agent = agentPtr;
(*msgPtr)._val = val;
//add to messages array:
assert(_msgArr != 0 && _waitingMsgs<MAX_MESSAGES);
_msgArr[_waitingMsgs] = msgPtr;
_waitingMsgs++;
}
My question is about the deletion of this array. I would like to delete the array and all allocated structs. if i write:
delete [] _msgArr
will this delete also each allocated struct or will free only the allocated memory for the array?
Is the correct way is to go over the entire array with a for loop and write
delete _msgArr[i]
and at last wite delete [] _msgArr to delete the allocated array ?
thanks!
Yes, you need to loop over all elements and delete
them manually before calling delete[]
on the array.
The delete []
will call the destructors on the struct pointers, which doesn't dispose of the structs or the _agent
members, which itself points to memory. You could call delete _msgArr[i]._agent
and then delete _msgArr[i]
in a loop, which will dispose of the Agent
and then the Message
.
First, though, you need to know who should get rid of the Agent
s, and when. If these are owned by another data structure, you shouldn't get rid of them when getting rid of _msgArr
, and looping over _delete _msgArr[i]
followed by delete [] _msgarr;
is all you need.
If you do need to delete the Agent
s also, you have three reasonable choices.
First, you can give Message
a destructor that will delete its _agent
. It should also have a copy constructor and assignment operator defined then, either to pass ownership or to copy, or else define them as private
so any attempt to use them will be a compile-time error.
Second, you could change the Agent *
to a smart pointer, so that the extra memory will be deleted when the Message
goes away.
Third, you could go through the loop I suggested above when getting rid of the array.
Unless you have good reasons to keep the code C-compatible, I'd suggest that you use a std::vector<boost::shared_ptr<Message> >
, and have Message
contain a boost::shared_ptr<Agent>
rather than an Agent *
(if you don't have to dispose of the Agent
s, Agent *
is fine). At that point, you don't need to worry: when _msgArr
goes out of scope, all the memory is cleaned up properly.
unfortunately yes. But you can simplify the thing with a couple of lines if you are going to do this a lot.
#include <algorithm>
// might already exists in a boost header (i don't remember)
template <T>
void delete_func(T* e) {
delete e;
}
// then, to delete your array :
std::for_each(_msgArr,_msgArr+MAX_MESSAGES, delete_func);
delete[] _msgArr;
but i suggest not to do so. You could use a std::vector with auto_ptr or shared_ptr (depending on your use case). So you won't have to delete each element yourself because the auto_ptr will do so. You will just have to delete the std::vector
Except for the fact that it is within a class member function and uses new
and delete
, this is C code. You don't need to check the result of new
(allocation errors will throw), you shouldn't do your own dynamic arrays (that's what std::vector
is for), and you shouldn't manage dynamically allocated using dumb pointers.
What you want is std::vector< std::shared_ptr<Message> >
or one of boost's pointer containers.
精彩评论