7

私は Java でリンクされたリストを扱った経験が豊富にありますが、C++ でのこの単純な試みと混同してしまったようです。実行時にセグメンテーション違反が発生しています。これは、私が理解していることから、ヌルポインターの割り当てに関係していますが、解決策がありません。

編集:非常に役立つ回答をありがとうございました。コードは現在機能していますが、使用しようとしています

delete p;
linkedList::addNode の最後で、実行時にセグメンテーション違反が発生します。それがなぜなのか誰かが知っていたら、ただ興味がありますか?

これが私の更新されたコードです:

#include <iostream>
using namespace std;

class Node{
    public:
        int data;
    Node * next;
    Node(int x){
        data = x;
        next = NULL;
        }
    Node(int x, Node * y){
        data = x; 
        next = y;
        }
    };


class linkedList{
Node *head;
public:
    linkedList(){
        head = NULL;
        }
    void addNode(int value){
        Node *p;
        if(head == NULL)
            head = new Node (value, NULL);
        else{
            p=head;
            while(p->next !=NULL)
                p=p->next;
            p->next = new Node (value, NULL);
            }
        }
    void print(){
        Node * p;
        p = head;
        while(p != NULL){
            cout << p->data << "\n";
            p = p->next;
            }
        }
};


int main(void){
linkedList test;
test.addNode(4);
test.addNode(76);
test.addNode(12);
test.print();
return(0);
}
4

9 に答える 9

6

まず、linkedList::addNodemethod には、;に割り当てられる構造if (head = NULL)があります。オペレーターが必要です。head==

第二に、行について:

head = &(Node (value, NULL));

やや直感的でない理由により、これは機能しません。への参照を取得しますがNode、そのノードはメソッドが終了するとすぐに範囲外になり、それを参照しようとするとセグメンテーション違反が発生します。演算子を使用する必要がありますnew(他の同様の行と同じ):

head = new Node(value, NULL);

ノードを削除するメソッドを追加する場合は、deleteそのノードを確認してください。Java のように自動的にガベージ コレクションが行われることはありません。

サイドバー: 次のように何が起こるか考えてみてください: するとNode(value, NULL)、次のように宣言された一時変数を使用しています:

Node hiddenTempNode(value, NULL);

これは、スタック以外の場所にオブジェクトのスペースを割り当てません。これは、スタック上の anintと aNode *に別々の変数としてスペースを割り当てるのと非常によく似ています。その結果、メソッドを離れるとすぐにオブジェクトが消え、そのオブジェクトへのポインターを使用すると奇妙なことが起こります。

第三に、注意してください:next = NULL単一パラメーターのコンストラクターに設定して、常に値を持つようにすることができます。デフォルトのコンストラクターについても同様です。

4番目:あなたのメソッドは; になるlinkedList::printまでループし、 ;の値を出力しています。最初と最後のアイテムを取得したい場合は、これらのオカレンスをおそらく変更する必要があります。p->nextNULLp->nextp->nextp

于 2009-07-08T03:16:19.687 に答える
3

スタック上の変数のアドレスを取得しています

head = &(Node (value, NULL));

に変更する必要があります

head = new Node(value, NULL);

p->next コードについても同様です。次に、デストラクタでこれらのノードを削除します。

印刷のお試しは

while(p != NULL)
{
   cout << p->data << "\n";
   p = p->next;
}
于 2009-07-08T03:15:26.630 に答える
2

初心者向け

if(head = NULL)

は代入であり、等しいかどうかのチェックではありません。に変更します

if(head == NULL)

第二に、

head = &(Node (value, NULL));

意味がありません* これを次のように変更します

head = new Node (value, NULL);

*これは実際に一時オブジェクトを作成し、アドレスを提供してから、新しく作成されたオブジェクトを破棄します。

第三に、

Node(int x) { data = x; }

値なしのままnextにして、この行を次のように変更します

Node(int x) { data = x; next = NULL; }
于 2009-07-08T03:14:01.063 に答える
2

スタック上のノードにスペースを割り当て、そのアドレスを取得しています。これは、ブロックが終了するとすぐに消え、その結果、アドレスは無効になります。new代わりに、演算子を使用してヒープにノードを割り当てる必要があります。

Node* node = new Node(value, NULL);

メモリリークを防ぐために、必要がなくなったらすぐにヒープに割り当てたものをすべて解放する必要があります。

delete node;
于 2009-07-08T03:14:33.027 に答える
1

メモリを割り当てていません。割り当てるには new を使用する必要があります。

if(head = NULL) のもう 1 つのエラーです。if(head == NULL) である必要があります。

void addNode(int value){
            Node *p;
            if(head == NULL)
                    head =  new Node (value, NULL);
            else{
                    p=head;
                    while(p->next !=NULL)
                            p=p->next;
                    p->next = new Node (value, NULL);
                    }
            }
于 2009-07-08T03:15:14.197 に答える
1

まだ言及されていない 2 つの問題を追加したいと思います。

  • オブジェクトを「新規」にするときは、ある時点でそれらを「削除」する必要があります。
  • 3 つのコンストラクターはすべて、両方のメンバー変数を初期化する必要があります。
于 2009-07-08T03:22:48.100 に答える
1

あなたの削除ステートメントは、実際にはクリーンアップを行っていません。p==null と呼ぶ頃には。リストをクリーンアップしたい場合は、個別のメソッドを実装して反復し、すべてのノードを削除する必要があります。

このようなもの:

void ClearList ()
{
    Node * c = head;
    Node * n;

    while (c != NULL)
    {
        n = c->next;
        delete c;
        c = n;
    }
}
于 2009-07-08T03:55:35.760 に答える
0

コードは現在機能していますが、使用しようとしています

delete p;

linkedList::addNode の最後で、実行時にセグメンテーション違反が発生します。それがなぜなのか誰かが知っていたら、ただ興味がありますか?

ノード追加関数の目的は、LinkedList の最後に新しいノードを動的に割り当てることだったので、これは問題です。'delete p;' 新しく追加されたノードを削除しています(実際には望んでいないと思います)。ただし、これがセグメンテーション違反を引き起こす理由であるあなたの質問に答えるには:

ノードを追加し、head にこの新しいノードを指すように指示します。ここで、もう一度 NULL を指す必要があることを head に通知せずに、この新しいノードを削除します。したがって、次にノードを追加するか、リストを印刷しようとすると、実際には解放された (削除された) メモリ、kaboom?

リスト内の削除の正しい (または少なくとも 1 つの正しい) 使用法はデストラクタにあります。C++ では、割り当てた動的メモリを常にクリーンアップする必要があることを思い出してください。デストラクタは次のようになります。

~linkedList()
{
    Node* p = head;
    while ( p!=NULL )
    {
        Node* nextNode = p->next;
        delete p;
        p = nextNode;
    }
}

このようなデストラクタを使用することで、linkedList がスコープ外になったとき、または削除されたときに適切にクリーンアップされることが保証されます。

于 2009-07-08T05:27:08.493 に答える
-2

解決策: 独自のリンク リストを実装しないでください。標準ライブラリで提供されているものを使用してください。

于 2009-07-08T03:30:32.330 に答える