为什么删除两次相同的内存时没有错误?

时间:2013-01-12 02:46:53

标签: c++ memory

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中成功运行时,事实并没有发生。 我不明白为什么没有发生错误。

2 个答案:

答案 0 :(得分:6)

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

请参阅:c++ delete (wikipedia)

答案 1 :(得分:0)

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