Я пытаюсь реализовать связанный список, используя shared_ptr, а не сырые указатели.Код:
#include <memory>
class NodeTest
{
private:
int v;
std::shared_ptr<NodeTest> next;
public:
NodeTest() { v = 0; };
NodeTest(unsigned int i) { v = i; }
~NodeTest() {};
void setNext(std::shared_ptr<NodeTest> & toSet) { next = toSet; }
};
std::shared_ptr<NodeTest> init()
{
std::shared_ptr<NodeTest> elt = std::shared_ptr<NodeTest>(new NodeTest());
std::shared_ptr<NodeTest> first = elt;
for (unsigned int i = 1; i < 5000; i++)
{
std::shared_ptr<NodeTest> next(new NodeTest(i));
elt->setNext(next);
elt = next;
}
return first;
}
void test_destroy()
{
std::shared_ptr<NodeTest> aList = init();
}
int main(int argc, char * argv[])
{
test_destroy();
}
Это генерирует переполнение стека при выходе из области действия test_destroy()
из-за вызова деструктора aList
(RAII).Чтобы уничтожить aList
, он вызывает деструктор next
и т. Д., Который, очевидно, заканчивается потоком стека для достаточно большого списка.
Я не могу найти какой-либо эффективный способ исправить это.Идеальным вариантом было бы удалить текущую NodeTest
перед тем, как перейти к удалению next
, верно?Как бы вы поступили так?
Заранее спасибо
Решение: Вам необходимо разорвать связи между всеми узлами И сохранить указатель на каждый узел так, чтобыДеструктор не сразу вызывается при разрыве ссылок.Пример ниже с использованием вектора.
~NodeTest()
{
std::vector<std::shared_ptr<NodeTest>> buffer;
std::shared_ptr<NodeTest> cursor = next;
while (cursor.use_count()!=0)
{
std::shared_ptr<NodeTest> temp = cursor->getNext();
cursor->setNext(std::shared_ptr<NodeTest>());
buffer.push_back(cursor);
cursor = temp;
}
next = std::shared_ptr<NodeTest>();
};