3

MySinglyLinkedList.h:

#include <iostream>

template<class T> class LinkedList;

template<class T>
class LinkedNode {   
 public:
  LinkedNode(T new_data):data(new_data) {; }

 private:
  friend class LinkedList<T>; 
  LinkedNode<T> *next;
  T data;
};

template<class T>
class LinkedList {   
 public:
  LinkedList();
  ~LinkedList();
  void PushNode(T new_data);
  void Delete(LinkedNode<T> *pnode);
  void Show();

 private:
  LinkedNode<T> *head; //Head pointer
  LinkedNode<T> *tail; //Tail pointer
  int length;          //Length of the list
};

//Initialize an empty list when creating it
template<class T>
LinkedList<T>::LinkedList()
{
  head = tail = NULL;
  length = 0;
}

//delete all the nodes when deconstructing the object
template<class T>
LinkedList<T>::~LinkedList()
{
  LinkedNode<T> *ptr = head;
  while (ptr)
  {
    LinkedNode<T> *ptr_del = ptr;
    ptr = ptr->next;
    Delete(ptr_del);
  }
}

//Add one node to the tail of the list
template<class T>
void LinkedList<T>::PushNode(T new_data)
{
  LinkedNode<T> *pnew_node = new LinkedNode<T>(new_data);
  pnew_node->next = NULL;
  if (!length) {
    head = tail = pnew_node;
    length++;
  } else {
    tail->next = pnew_node;
    tail = pnew_node;
    length++;
  }
}

//Delete the node pointed by pnode
template<class T>
void LinkedList<T>::Delete(LinkedNode<T> *pnode)
{
  LinkedNode<T> *ptr = head;
  if (pnode==head) {
    head = pnode->next;
  } else {
    while(ptr->next != pnode)
    {
      ptr = ptr->next;
    }    
    ptr->next = pnode->next;
  }
  if(pnode == tail)
     tail = ptr;

  delete pnode;
  length--;
}

template<class T>
void LinkedList<T>::Show()   //Print all the contents in the list
{
  LinkedNode<T> *pnode = head;
  while(pnode)
  {
    std::cout << pnode->data << std::endl;
    pnode = pnode->next;
  }
  std::cout << "In total: " << length << std::endl;  
}

主な機能は次のとおりです。

#include "MySinglyLinkedList.h"
#include <cstdlib>
#include <ctime>

using namespace std;

int main(int argc, char *argv[])
{
  //list_len is the length of the list
  int list_len = 5;
  srand(time(0));
  if (argc > 1)
    list_len = atoi(argv[1]);

  LinkedList<int> test_list;   //Create the first list: test_list

  for (int i = 0; i < list_len; i++)
  {
    //The elements in the list are random integers
    int cur_data = rand()%list_len;      
    test_list.PushNode(cur_data);
  }
  test_list.Show();

  LinkedList<int> test2 = test_list;  //Create the second list: test2
  test2.Show();

  return 0;
}

ここではコピーコンストラクターを定義しなかったため、デフォルトのコピーコンストラクターが呼び出され、2番目のリストを作成するときにビットコピーが実行され、その結果test_listtest2同じリンクリストを指します。したがって、リストの最初のノードは、2つのオブジェクトが分解されるときに2回削除されます。しかし、GCCを使用してプログラムをコンパイルしたとき、実際には何も問題はなく、Linuxで正常に実行されました。エラーが発生しなかった理由がわかりません。

4

2 に答える 2

6

既に削除されたポインターを削除すると、未定義の動作が発生するため、何かが起こる可能性があります。何も起こらないようにしたい場合は、削除後にポインターを null に設定します。削除nullしても何も起こらず、エラーにもなりません。

参照: c++ 削除 (ウィキペディア)

于 2013-01-12T02:58:42.033 に答える
0

Diego の回答によると、C++ 標準では NULL ポインターの削除が許可されています。コンパイラは、2 回目にポインタを削除したときにポインタに含まれる値を知る方法がありません (つまり、NULL の可能性があります)。したがって、標準に準拠するためにポインタを許可するしかありません。

于 2013-01-12T03:03:49.383 に答える