2016-06-02 6 views
0

私の質問を確認していただきありがとうございます。私は現在、演算子の "削除"に関する本当に基本的な質問を持っています。右の子を削除するとnullptrへの親ポインタの左ポインタ

template <typename T> 
    void Tree<T>::remove(const unsigned& index, TreeNode<T>*& tree) 
    { 
     if(tree == nullptr) 
     { 
      std::cerr << "remove: can't find target" << std::endl; 
     } 
     else if(index < tree->index) 
     { 
      remove(index, tree->left); 
     } 
     else if(index > tree->index) 
     { 
      remove(index, tree->right); 
     } 
     else if(index == tree->index) 
     { 
      if(tree->degree() == 2) 
      { 
       tree->index = findMin(tree->right)->index; 
       tree->value = findMin(tree->right)->value; 
       remove(tree->index, tree->right); 
      } 
      else 
      { 
       auto oldNode = tree; 
       tree = (tree->left != nullptr) ? tree->left: tree->right; 
       delete oldNode; 
    //   oldNode = nullptr; 

      } 
     } 
    } 

上記のコードは古典的な検索ツリー削除アルゴリズムです。現在のツリーにルート(キーが3に等しい)と右の子(たとえばキーが4と等しい)の2つのノードしかない場合、ノード4を削除すると、removeを2回呼び出してこの行に移動します:

delete oldNode; 

この行では「oldNode」が削除されますが、現在は4です。私の知る限り、delete演算子はメモリアドレスを解放します(アドレスはoldNodeの値と同じです)。つまり、OSがこのアドレスを再び使用できるようにします。ですから、私はrootの右ポインタ(root-> right)の値を表示すると、アドレスを取得する必要があります。実際に私が印刷するとき、私は0を得ます。

私は私の質問を明確に説明します。それは愚かな質問かもしれません、私は混乱を起こした場合私に知らせてください。

答えて

1

あなたが見ているのは、削除後のポインタの使用が未定義の動作(C++ 14まで)であると思います。

C++の場合14:この方法で無効になり、割り当て解除関数(二重削除)に渡すポインタによる間接参照は、未定義の動作です。その他の用途は実装定義です。

未定義の動作では、基本的には、削除後にポインタを使用して、その値を変更することもできます。

あなたの実装がdeleteの中のnullptrへのポインタの値を設定するようです。

+0

こんにちは、ありがとうございます。実際に私は "oldNode = nullptr"を書き留めました。私の質問は、 "この実装では、子ノードが削除された場合、いつnullptrへの親の右ポインタを設定するか" –

0

私は答えを見つけましたが、答えの前に私の質問を明確にしてください。問題は、子がいつ削除されるか、誰がnullptrに親の右ポインタを設定するかを尋ねることです。答えは、この関数は引数としてポインタ参照を持っています。この関数を呼び出すと、渡されたパラメータ自体がnullptrに設定されます。たとえば、root-> rightを渡すと、root-> rightを直接nullptrに設定できます。

関連する問題