2015-11-08 9 views
5

मैं एक एसडब्ल्यूई सीखने सी ++ हूं, और head और next के संदर्भ के रूप में std :: unique_ptr का उपयोग करके एक सरल लिंक्डलिस्ट क्लास का निर्माण कर रहा हूं।सी ++ smart_ptr स्टैक ओवरफ़्लो का कारण नहीं बनता है?

template <class T> 
struct LinkedListNode { 
    T value; 
    std::unique_ptr<LinkedListNode<T>> next; 

    // For debugging. 
    ~LinkedListNode() { 
     std::cout << "destructed for value " << this->value << std::endl; 
    } 
}; 

template <class T> 
struct LinkedList { 
    std::unique_ptr<LinkedListNode<T>> head; 
}; 

स्मार्ट संकेत का उपयोग करना, मैं उम्मीद करते हैं कि जब एक LinkedList उदाहरण नष्ट कर दिया या क्षेत्र से बाहर चला जाता है जाता है, तो head हटा दिया जाएगा, और प्रत्येक next नोड रिकर्सिवली भी हटा दिया जाएगा: यह बुनियादी संरचना है।

और यह वही होता है जो वास्तव में होता है। हालांकि, वास्तव में लंबी सूचियों (~ 20 एम नोड्स) के साथ काम करते समय, यह आश्चर्यजनक रूप से अभी भी ठीक काम करता है। एक ढेर अतिप्रवाह के कारण यह दुर्घटनाग्रस्त नहीं होना चाहिए?

क्रम बहुत मोटे तौर पर मेरी ओएस ढेर के आकार का अनुमान में, मैं निम्नलिखित स्क्रिप्ट लिखा है:

int main() { 
    struct s { 
     static void p(int i) { 
     std::cout << i << std::endl; 
     p(i+1); 
    }; 
    s::p(0); 
} 

और यह यात्रा नंबर पर दुर्घटनाग्रस्त हो गया ~ 175K, 20M नोड्स है कि मैं कर रहा था की तुलना में कम पहले deallocate। क्या हो रहा है? क्या मैं unique_ptr के तरीके के बारे में कुछ याद कर रहा हूं?

+0

यह 'std :: unique_ptr' के स्मार्ट उपयोग की तरह नहीं दिखता है। एक 'unique_ptr' को पकड़ना मतलब किसी ऑब्जेक्ट पर स्वामित्व का मालिकाना है। एक लिंक्ड सूची में एक नोड अगले नोड पर स्वामित्व नहीं रखता है, यह अपने आप में मौजूद डेटा पर स्वामित्व रखता है। – Jack

+0

क्या आप जिस कोड पर चर्चा कर रहे हैं उसे पोस्ट कर सकते हैं ताकि अन्य संकलित हो सकें और देखें कि क्या होता है? – Ruslan

+0

निश्चित रूप से! https://gist.github.com/manuelmenzella/0fd85280d5051abec2c7 बहुत कठोर मत बनो;) –

उत्तर

2

आपके उदाहरण में आप वास्तव में रिकर्सन कर चुके हैं, इसके पीछे वास्तविक कारण स्टैक ओवरफ़्लो तक नहीं पहुंच सकता क्योंकि यह tail-call recursion है जिसे एक पुनरावर्तक समाधान के लिए अनुकूलित किया जा सकता है।

कोड के इस स्निपेट के साथ:

struct Node 
{ 
    int value; 
    std::unique_ptr<Node> next; 

    Node(int value, Node* next) : value(value), next(next) { } 

    ~Node() 
    { 
    if (value == 0) 
     cout << "foo" << endl; 
    } 
}; 

int main() 
{ 
    Node* node = new Node(0, nullptr); 
    for (int i = 1; i <= 5; ++i) 
    node = new Node(i, node); 

    delete node; 

    return 0; 
} 

cout विवरण पर एक ब्रेकपाइंट रखने और स्टैक ट्रेस आप स्पष्ट रूप से उस व्यवहार को देखने का निरीक्षण करके पुनरावर्ती है:

enter image description here

व्यवहार है ~Node() रिटर्न पर ट्रैक करने के लिए आधार विनाशक का उपयोग करके here भी दिखाया गया है।

चूंकि next नोड को विनाशक से लौटने से पहले नष्ट किया जाना चाहिए, जिससे ~Node() का पुन: प्रयास किया जाता है। यह व्यवहार कच्चे पॉइंटर्स का उपयोग करके और विनाशक में सीधे अगले सूचक को हटाकर समान होगा, जो वास्तव में पहले से ही here का उत्तर दिया जा चुका है।

संबंधित मुद्दे