Да, это утечка памяти, так как общий указатель в Node
никогда не будет удален.Подумайте:
#include <iostream>
#include <memory>
class Node {
std::shared_ptr<Node> m_ptr;
public:
Node() { std::cout << "constructor\n"; }
~Node() { std::cout << "destructor\n"; }
void storeChild(std::shared_ptr<Node> ptr) { m_ptr = ptr; }
long use_count() { return m_ptr.use_count(); }
};
int main() {
Node* n = new Node;
{
std::shared_ptr<Node> bc_ptr(n);
bc_ptr->storeChild(bc_ptr); // this line is the bug
std::cout << n->use_count() << "\n"; // prints 2
}
std::cout << n->use_count() << "\n"; // prints 1
// the Node pointed to by n is leaked
}
Возможно, это будет еще более очевидно, если вы сделаете так:
#include <iostream>
#include <memory>
class Node {
std::shared_ptr<Node> m_ptr;
public:
Node() : m_ptr(this) { std::cout << "constructor\n"; }
~Node() { std::cout << "destructor\n"; }
};
int main() {
new Node;
}
Если вы попытаетесь:
int main() {
delete new Node;
}
Деструктор Node
будетбыть вызванным дважды.Во-первых, вашим delete
, а затем shared_ptr
, когда он удален.
Предотвращение может быть сложным, если возможно иметь круговое владение, например: A-> B-> C-> A... Вы, вероятно, должны использовать std::weak_ptr
, если это риск.