Próbuję zaimplementować połączoną listę za pomocą ShareD_PTR, a nie surowe wskaźniki. Kod :

#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();
}

Jest to generowanie stackoverflow podczas opuszczania test_destroy() zakres ze względu na połączenie do aList destructor (RAII). Aby zniszczyć aList, wywołuje destruktor next i tak dalej, co oczywiście kończy się stackoverflow dla wystarczającej dużej listy.

Nie mogę znaleźć żadnego skutecznego sposobu naprawienia tego. W idealnym przypadku będzie usunąć prąd NodeTest przed przejściem do next usunięcie, prawda? Jak byś coś zrobił?

Z góry dziękuję

Rozwiązanie: Musisz złamać linki między wszystkimi węzłami i zaoszczędzić wskaźnik do każdego węzła, aby destruktor nie był natychmiast wywołany po łamaniu linków. Przykład poniżej przy użyciu wektora.

~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>();
};
1
Spazz 21 luty 2019, 17:48

2 odpowiedzi

Najlepsza odpowiedź

W takim przypadku powinieneś zarządzać węzłami ręcznie, ponieważ destructor dzwoni do niszczeniach wywołuje destructor .....

Spójrz na rozmowę .

1
Alex 21 luty 2019, 15:09

Destruktor NodeTest wywołuje destruktor NodeTest::next, który rekurencyjnie wywołuje inny destruktor NodeTest i tak, aż stos jest wyczerpany. Inteligentne wskaźniki nie powinny być używane do łączenia węzłów z tego powodu.

0
Maxim Egorushkin 21 luty 2019, 15:14