-3

最初のメソッド append() でこれまでに得た、C++ で独自に単一リンク リストをゼロから実装しようとしています。

#include <iostream>
using namespace std;

struct ListNode{
    int key_value;
    ListNode *next;
};

class List{ 
    public:
        List();
        void append(int key);

    private:
        ListNode *head;
        ListNode *tail;
};

List::List(){
    head = NULL;
    tail = head;
}

void List::append(int key){
    ListNode *newnode;
    newnode->key_value = key;
    newnode->next = NULL;

    if(head == NULL){
        head = newnode;
        tail = head;
    }
    else{
        tail->next = newnode;
        tail = newnode;
    }
    return;
}

int main(){
    try{ 
        List l1;
        l1.append(1);
        //l1.append(2);
        //l1.append(3);
        //l1.append(5);
    } 
    catch (exception const& ex) { 
        cerr << "Exception: " << ex.what() <<endl; 
        return -1;
    } 
}

警告やエラーなしでコンパイルされますが、実行中にメッセージが表示されるだけですBus error: 10ListNode変数とポインターを初期化して使用する方法に問題があるようです。洞察をいただければ幸いです。

4

1 に答える 1

1

この行で:

ListNode *newnode;

へのポインタの初期化されていない変数を作成してからListNode、それを逆参照します。初期化されていない変数にアクセスすると UB が発生しますが、ポインターを使用すると、すぐにバス エラーが発生する可能性があります。したがって、メモリを割り当てます。

ListNode *newnode = new ListNode;

注: データ メンバーを初期化する代わりに:

newnode->key_value = key;
newnode->next = NULL;

次の適切なコンストラクターを提供する必要がありますListNode

struct ListNode {
    int key_value;
    ListNode *next;

    ListNode( int v ) : 
        key_value( v ),
        next( nullptr )
    {
    }
};

それを作成するだけです:

  ListNode *newnode = new ListNode( key );

次の 2 行は省略できます。ListNodeこれにより、コードがよりクリーンになり、初期化されていないデータでインスタンスが作成されるのを防ぐことができます。

注 N2: クラスListには生のポインターとデータの所有権があるため、3 つのルールに従い、コピー ctor、代入演算子、および dtor を作成または無効にする必要があります。

于 2016-07-19T21:46:25.587 に答える