Я программирую ориентированный граф на C ++. Указатели на узлы графа в списках смежности узлов моего графа будут повреждены, если я инициализирую их определенной функцией, использующей обработку исключений, но списки не будут повреждены, если я инициализирую их с помощью аналогичной функции, которая не использует обработку исключений.
Мой класс графа имеет функцию с таким заголовком:
bool directed_edge(const Key& parent, const Key& child) throw(std::invalid_argument);
... и другая функция с этим заголовком:
std::tuple<bool, bool, bool> add_directed_edge(const Key& parent, const Key& child);
directed_edge
выдает исключение, если либо parent
, либо child
отсутствует на текущем графике. add_directed_edge
работает, вызывая directed_edge
и обрабатывает исключение, фактически добавляя узлы в список и затем , соединяя их с ребром.
Если я использую directed_edge
для создания своих ребер, то никакого искажения данных нет вообще - списки смежности узлов графа содержат ожидаемые данные. Однако, если я использую add_directed_edge
, данные будут повреждены. Это странно, поскольку add_directed_edge
на самом деле мало что делает, кроме вызова directed_edge
и обработки любых потенциальных ошибок, которые он может выдать. Это наводит меня на мысль, что это как-то связано с обработкой исключений внутри функции, но я не совсем уверен.
Вот реализация для обеих функций:
template<typename Key>
bool graph<Key>::directed_edge(const Key& parent, const Key& child) throw(std::invalid_argument)
{
node* parentItor = find_node(parent);
node* childItor = find_node(child);
// Return true if the edge was added
return parentItor->directed_edge(childItor);
}
template<typename Key>
std::tuple<bool, bool, bool>
graph<Key>::add_directed_edge(const Key& parent, const Key& child)
{
bool parentAdded;
bool childAdded;
bool edgeAdded;
// Try to add the directed edge. Exception thrown if either doesn't exist
try {
edgeAdded = directed_edge(parent, child);
return std::make_tuple(false, false, edgeAdded);
}
catch(std::invalid_argument& invArg) {
// Add parent and child, and assign to see if they needed to be added
parentAdded = add(parent);
childAdded = add(child);
// Add the directed edge
edgeAdded = directed_edge(parent, child);
return std::make_tuple(parentAdded, childAdded, edgeAdded);
}
}
Я понимаю, что обе эти функции вызывают много других функций, поэтому, если вы хотите увидеть больше деталей реализации, вы можете оставить комментарий, и я должен скоро вернуться к вам
Я провел три теста с некоторыми основными данными. В первом тесте я вручную добавил узлы 0-9, затем использовал directed_edge
, чтобы установить несколько соединений. Результат таков:
0 -> 1, 3
1 -> 2, 4, 6, 7
2 -> 3, 8, 9
3 ->
4 -> 6, 7, 5
5 ->
6 -> 7
7 ->
8 ->
9 ->
Во втором тесте я не добавлял вручную узлы на график. Я неоднократно вызывал add_directed_edge
, поскольку эта функция предназначена для добавления узлов каждый раз, когда ей дается ключ к несуществующему узлу. Результат таков:
0 -> 284985109, 976560249
1 -> 1752440936, 116, 17504392, 7
3 ->
2 -> 1768366181, 8, 9
4 -> 6, 7, 5
6 -> 7
7 ->
8 ->
9 ->
5 ->
Кроме того, чтобы быть точным, я провел третий тест, в котором я вручную добавил все узлы и затем вызвал add_directed_edge
, чтобы установить соединения на уже существующих узлах. Интересно, что это дало ожидаемые результаты:
0 -> 1, 3
1 -> 2, 4, 6, 7
2 -> 3, 8, 9
3 ->
4 -> 6, 7, 5
5 ->
6 -> 7
7 ->
8 ->
9 ->