2016-06-17 18 views
6

謝謝你檢查我的問題。當我實施BST時,我遇到了一個非常基本的問題,那就是「分配指針的不同方法有什麼不同?」我們都知道一個指定點可以使用:分配指針的方式有什麼區別?

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

謝謝你的迴應,真的很感激。所以,如果我理解正確,我得到錯誤的原因是因爲在堆中聲明的變量超出範圍時將被釋放,所以,在第一種情況下,「節點」將被釋放並且指針「樹」將被重置爲「nullptr」,對嗎? –

+0

@XiangyuZhang不,在堆中分配的內存不會被釋放,除非你明確這樣做(這就是爲什麼你在第二種情況下沒有問題)。對於第一種情況,一旦_insert的棧幀被彈出,指針「tree」將不會被重置爲「nullptr」,它仍然保持原來的狀態,但是因爲_insert()已經返回,所以「tree」指向只是隨機存儲器(以下函數調用的堆棧框架將覆蓋已分配的堆棧存儲器),解引用/訪問「樹」指針肯定會產生問題。 –

+0

@ XgygyuZhang也許這對於查看https://en.wikipedia.org/wiki/Call_stack#STACK-FRAME很有幫助 –

3

沒有,這兩種方式不應該是相同的:

  • 的第一項任務p = &q是完全有效的,因爲q是在內存中的實際對象,p是一個指向它
  • 第二賦值p = q分配一個單元化指針qp,這是未定義的行爲。

這就是兩種實現不同的原因。

如果您想將q指定爲p,則需要先指定q本身。例如,您可以分配new int它:

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

然而,在這種情況下,你還不如直接分配給new intp

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

這意味着p現在具有整數q存儲在存儲器中的地址。

int *p, *q; 
p = q; 

在此,您正在將存儲在指針q中的地址複製到p。

相關問題