2016-06-17 16 views
6

मेरे प्रश्न की जांच के लिए धन्यवाद। जब मैं बीएसटी लागू कर रहा हूं, तो मुझे वास्तव में एक मौलिक समस्या का सामना करना पड़ा, यह है कि "सूचक को असाइन करने के लिए अलग-अलग दृष्टिकोणों में क्या अंतर है?" हम सभी जानते हैं आवंटित एक बिंदु का उपयोग कर सकते हैं:पॉइंटर निर्दिष्ट करने के तरीकों के बीच क्या अंतर है?

int *p, q; 
p = &q; 

या:

int *p, *q; 
p = q; 

वे एक ही होना चाहिए। लेकिन नीचे मेरे मामले में, वे पूरी तरह से अलग काम कर रहे:

template <typename T> 
void Tree<T>::_insert(TreeNode<T>*& tree, const T& value, const unsigned& key) 
{ 
// TreeNode<T> node(value, key); 
// if(tree == nullptr) tree = &node; 
    TreeNode<T> *node = new TreeNode<T>(value, key); 
    if(tree == nullptr) tree = node; 

    else if(key < tree->index) _insert(tree->left, value, key); 
    else if(key > tree->index) _insert(tree->right, value, key); 
    else if(key == tree->index) std::cerr << "_insert: repeating key" << std::endl; 
} 

पहला तरीका का उपयोग करना (एक विख्यात), समारोह पेड़ नोड के बराबर आवंटित नहीं होगा, जबकि दूसरा तरीका ठीक काम करता है।

तो, क्या यह मेरी गलती है, या वे स्वाभाविक रूप से अलग हैं?

उत्तर

3

पहले मामले में नोटिस करें:

// TreeNode<T> node(value, key); 
// if(tree == nullptr) tree = &node; 

node एक वस्तु ढेर पर आवंटित है।

दूसरे मामले में

TreeNode<T> *node = new TreeNode<T>(value, key); 
if(tree == nullptr) tree = node; 

nodeढेर पर आवंटित किया जाता है है।

अंतर यह है कि एक बार _insert फ़ंक्शन रिटर्न होता है, इसका स्टैक फ्रेम पॉप हो जाता है, और परिणामस्वरूप सभी स्थानीय चर/ऑब्जेक्ट अमान्य हो जाते हैं, परिणामस्वरूप, आपको स्मृति त्रुटियां मिलेंगी।

+0

आपकी प्रतिक्रिया के लिए धन्यवाद, वास्तव में इसकी सराहना करते हैं। इसलिए, अगर मैं सही ढंग से समझता हूं, तो मुझे त्रुटि मिली क्योंकि कारण ढेर में घोषित चर को मुक्त किया जाएगा जब यह दायरे से अधिक हो जाएगा, इसलिए, पहले मामले में, "नोड" मुक्त हो जाएगा और सूचक "पेड़" को रीसेट कर दिया जाएगा "नलप्टर", है ना? –

+0

@XiangyuZhang नहीं, ढेर में आवंटित स्मृति को तब तक मुक्त नहीं किया जाएगा जब तक आप स्पष्ट रूप से ऐसा नहीं करते (यही कारण है कि आपको दूसरे मामले में समस्या नहीं थी)। पहले मामले के लिए, सूचकांक "पेड़" को "nullptr" पर रीसेट नहीं किया जाएगा जब एक बार _insert के ढेर फ्रेम को पॉप किया जाता है, यह अभी भी वही रहेगा, लेकिन _insert() वापस आ गया है, तो "पेड़" क्या इंगित करता है केवल यादृच्छिक स्मृति है (निम्नलिखित फ़ंक्शन कॉल का स्टैक फ्रेम आवंटित स्टैक मेमोरी को ओवरराइट करेगा), "पेड़" पॉइंटर को संदर्भित/एक्सेस करना निश्चित रूप से समस्याग्रस्त होना है। –

+0

@XiangyuZhang शायद यह https://en.wikipedia.org/wiki/Call_stack#STACK-FRAME को देखने में सहायक है –

3

नहीं है, दो तरह से समान नहीं होना चाहिए:

  • पहला काम p = &q, पूरी तरह से वैध है, क्योंकि q स्मृति में वास्तविक वस्तु है, और यह करने के लिए p
  • दूसरा एक सूचक है असाइनमेंट p = q एक प्रारंभिक पॉइंटर q से p निर्दिष्ट करता है, जो अपरिभाषित व्यवहार है।

यही कारण है कि दो कार्यान्वयन अलग हैं।

यदि आप q से p असाइन करना चाहते हैं, तो q को पहले स्वयं को असाइन करने की आवश्यकता है। उदाहरण के लिए, आप इसे करने के new int आवंटित कर सकते हैं:

int *p, *q = new int; 
p = q; 

हालांकि, इस मामले में आप के रूप में अच्छी new int सीधे p को निर्धारित करना चाहेंगे।

0
int *p, q; 
p = &q; 

इसका मतलब है कि पी में अब पता है जिस पर पूर्णांक q को स्मृति में संग्रहीत किया जाता है।

int *p, *q; 
p = q; 

इसमें आप पॉइंटर q में संग्रहीत पते की प्रतिलिपि बना रहे हैं।

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