Я реализовал двоичное дерево поиска в С++. Вместо того, чтобы использовать указатели на указатели на дочерние узлы, я использовал 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;