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;
}

由于我在这里没有定义任何复制构造函数,因此在创建第二个列表时将调用默认的复制构造函数并进行位复制,结果test_listtest2指向同一个链表。因此,当两个对象被解构时,列表的第一个节点将被删除两次。但事实是,当我使用 GCC 编译程序时,并没有发生任何错误,并且它在 Linux 中运行成功。我不明白为什么没有发生错误。

4

2 回答 2

6

删除一个已经被删除的指针会导致未定义的行为,所以任何事情都可能发生。如果您想确保没有任何事情发生,请在删除后将指针设置为 null。删除null什么都不做,也不会导致错误。

参见:C++ 删除(维基百科)

于 2013-01-12T02:58:42.033 回答
0

根据 Diego 的回答,C++ 标准允许删除 NULL 指针。编译器无法知道第二次删除指针时将包含什么值(即它可能为 NULL),因此它别无选择,只能允许它符合标准。

于 2013-01-12T03:03:49.383 回答