Короткий ответ на ваш вопрос, как и другие ответили уже есть: да, вызов деструктора eachover является проблематичным, поскольку это, вероятно, приведет к непредсказуемому поведению .
Например, посмотрите на эту ситуацию:
Vertex
объект v
время удаления
- , что приводит к удалению 1
Edge
в векторе член m_edge
,
- , что приводит к удалению оба
m_head
и m_tail
Vertex
,
- Предполагая, что один из них
v
, затем следующий цикл в v
деструктор попытается получить доступ к удаленным данным!
В лучшем случае ваша программа будет segfault; в худшем случае ... кто знает ...
Ваш дизайн не так уж плох. Однако его проблема заключается в том, что вы не можете четко определить право собственности (которое могло бы помочь узнать, кто должен уничтожать кого).
Действительно, предполагая Vertex
может быть в связи с несколькими (и, по меньшей мере, один) Edge
и что Edge
в связи с точно два Vertex
, то вы можете считать, что Edge
принадлежит паре Vertex
. Не так просто управлять порядком удаления в этой ситуации ...
Однако вам не обязательно нужно отношение собственности к государству, которое должно уничтожить кого. Как предполагалось выше, Edge
относится к точно двум Vertex
; если один из них уничтожен, то также должен быть уничтожен Edge
. С другой стороны, если уничтожен Edge
, нет никаких оснований для уничтожения любого из Vertex
по отношению к нему, поскольку каждый из них по-прежнему может быть связан с другими существующими Edge
; единственным исключением является то, что Vertex
не имеет никакого отношения к любому Edge
. Код следующие правила является следующее:
struct Edge;
struct Vertex {
public:
// ctors unchanged
~Vertex(); // implemented below
void remove_relation(Edge* edge) // for use by Edge only
{
std::vector<Edge*>::iterator it =
std::find(m_edge.begin(), m_edge.end(), edge);
if (it != m_edge.end())
m_edge.erase(it);
if (m_edge.size() == 0)
delete this; // this Vertex can be safely deleted
}
string m_name;
vector<Edge*> m_edge;
};
struct Edge {
public:
// ctors unchanged
~Edge() {
// Only have to remove relation with m_head & m_tail
if (m_head)
m_head->remove_relation(this);
if (m_tail)
m_tail->remove_relation(this);
std::cout << "deleted Edge " << this << std::endl;
}
void delete_from_vertex(Vertex* from) // for use by Vertex only
{
// Prevent from removing relation with the calling Vertex
if (m_head == from)
m_head = nullptr;
else if (m_tail == from)
m_tail = nullptr;
else
assert(false); // Vertex not in relation with this Edge
delete this; // finally destroy this Edge
}
string m_name;
Vertex* m_head;
Vertex* m_tail;
};
Vertex::~Vertex() {
for(int i = 0; i < m_edge.size(); i++)
m_edge[i]->delete_from_vertex(this); // special destruction
std::cout << "deleted Vertex " << this << std::endl;
}
Live example
который один является «владельцем» и который один «принадлежит»? Владелец делает удаление. –
Где находится 'new()', соответствующая 'delete'? –