Я реализовал двоичное дерево поиска в С++. Вместо того, чтобы использовать указатели на указатели на дочерние узлы, я использовал std::shared_ptr. Узлы дерева реализованы следующим образом:
struct treeNode;
typedef std::shared_ptr<treeNode> pTreeNode;
struct treeNode {
T key;
pTreeNode left;
pTreeNode right;
treeNode(T key) : key(key), left(nullptr), right(nullptr) {}
};
При удалении node из BST один из случаев - когда node имеет только один ребенок. node просто заменяется этим дочерним элементом, как показано ниже:
| remove node
node ---------> |
\ right
right
В подобной реализации Java это может быть закодировано как:
node = node.getRight();
В моей реализации на С++ это:
node = node->right;
где node имеет тип pTreeNode.
При вызове оператора = на pTreeNode (std::shared_ptr<TreeNode>) будет вызываться деструктор node. Количество общих указателей, указывающих на базовый TreeNode, равно 1, поэтому TreeNode уничтожается, освобождая его память. Когда вызывается деструктор TreeNode (по умолчанию), каждый из его членов уничтожается. Это, несомненно, приведет к уничтожению члена pTreeNode right. Проблема в том, что node->right - это то, что присваивается node. При тестировании моего BST он работает нормально, без ошибок/утечек памяти.
- Что я делаю небезопасно?
- Если это небезопасно, что я могу сделать, чтобы обойти эту проблему?
"Хак", который, как я полагал, может работать, будет заключаться в том, чтобы сделать еще один указатель, чтобы увеличить счетчик ссылок. Будет ли это адекватным решением?
//increase reference to node->right by 1 so it doesn't get destroyed
pTreeNode temp(node->right);
node = node->right;