2016-03-19 32 views
1

私はポインタと削除ポインタがC++でどのように働いたのか不思議に思ったので、私は実験を設定しました。私はこれが正常にリスト内のすべてのノードを削除したとリンクリスト内のすべてのノードを「完全に」削除するにはどうすればよいですか?

void deleteList(Node *node) { 
    if (!node) 
     return; 
    deleteList(node->next); 
    cout << "deleting node " << node->data << endl; 
    delete node; 
    node = nullptr; 
} 

:私は非常に単純な、単一リンクのリストがあり、リスト内のすべてのノードを削除し、次の再帰関数を作りました。

List list; 
// appending a bunch of numbers to the list... 
list.deleteList(list.head); 
if (list.head) 
    cout << true; 

これはヘッドが実際にまだ存在しないことを意味し、コンソールに1を出力します。ただし、メインでこの関数を呼び出した後、私は、ヘッドノードがまだ存在するかどうかを確認します。私は頭とそれの後のすべての他のノードがnullになることを期待しています。したがって、if条件が失敗するのは、ポインタをnullに設定することが再帰関数で最後に行うことです。だから、なぜ頭がまだ存在していると報告しているのですか?

編集:変更されたリストlist();リストへ

+1

'リストリスト();'はあなたの考えではありません。 [Most Vexing Parse](https://en.wikipedia.org/wiki/Most_vexing_parse) – Mahesh

+0

はい、私は実際に私の実験で2つのコンストラクタを持っています。上記の私の例では、サイズのために0や新しい空のヘッドノードのような値を初期化する他のコンストラクタを呼び出します。 – Manuel

+1

ステートメントはコンストラクタをまったく呼び出さない。戻り値の型が 'List'の関数' list'の宣言です。オブジェクトの初期化のために、 '()'を削除する必要があります。 – Mahesh

答えて

4

メモリを解放しましたが、nullptrへの割り当ては、呼び出し元の元のポインタではなく、関数に渡されたポインタのコピーにのみ影響します。

void deleteList(Node *&node) { 

その後、node = nullptr;の割り当ては、同様の発信者に影響を与える:あなたが参照によってポインタを受け取るとしての機能を宣言した場合

。あなたはこのC++ 11をタグ付けするので、それは言及を避けるために、双方向だ場合は、それだけで逆方向に順方向(生のポインタでstd::unique_ptr<Node>の一連のリンクリストを定義するために、通常ははるかに簡単だ

マインドサイクル)ので、特別なdeleter関数の必要性を避けることができ、単にヘッドポインタをnullptrに設定し、C++に削除をカスケードする作業をさせます。

編集std::unique_ptrは仕事をさせるに欠陥があります。コメントで指摘されているように、これはリストのサイズがスタックによって効果的に制限されていることを意味し、大きすぎるリストは削除するとスタックのオーバーフローを引き起こします。したがって、明示的に1つずつクリアする(最も簡単な方法は、適切にポップを実装することであり、headがメソッドでnullptrに変換されるまでクリアするだけです)は安全です。私は後世のために元の提案を残したので、この説明は理にかなっています。

+0

パーフェクト、明確化のためにありがとう。私はポインタが常に参照によって渡されたと思った。 私はユニークなポインタについて聞いています(これが呼び出されたのは初めてですか?)。これらの詳細については、 – Manuel

+0

@MannyKim:Yup、[unique pointers](http://en.cppreference.com/w/cpp/memory/unique_ptr)を参照する必要があります。ポインタ自体は値渡しであるため、ポインタは面白いです。どちらのポインタも最初は同じメモリを参照していますが、呼び出し先のポインタを変更しても呼び出し元には影響しませんが、指し示されているデータだけが変更されます(メモリはその場所に解放されます。他の機能によって解放されます)。 – ShadowRanger

+0

ちょうど明確であるために、 "解放されたポインタ"は "ノードを削除する"と "ポインタを参照解除する"を指します "ノード= nullptr"を参照してください、それは正しいですか?そして、それは本当に*(それが参照サイクルを避けるために、双方向だ場合は逆方向の生のポインタ)それは少し楽にポインタに – Manuel

関連する問題