C++ 为什么会有';当我删除两次相同的内存时,是否没有错误?

C++ 为什么会有';当我删除两次相同的内存时,是否没有错误?,c++,memory,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>; LinkedNo

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;  
}
#包括
模板类链接列表;
模板
类LinkedNode{
公众:
LinkedNode(T新数据):数据(新数据){;}
私人:
朋友类链接列表;
LinkedNode*下一步;
T数据;
};
模板
类链接列表{
公众:
LinkedList();
~LinkedList();
void PushNode(T新的_数据);
作废删除(LinkedNode*pnode);
void Show();
私人:
LinkedNode*头;//头指针
LinkedNode*tail;//尾部指针
int length;//列表的长度
};
//创建空列表时初始化它
模板
LinkedList::LinkedList()
{
头=尾=空;
长度=0;
}
//解构对象时删除所有节点
模板
LinkedList::~LinkedList()
{
LinkedNode*ptr=头;
while(ptr)
{
LinkedNode*ptr_del=ptr;
ptr=ptr->next;
删除(ptr_del);
}
}
//在列表末尾添加一个节点
模板
void LinkedList::PushNode(T新的\u数据)
{
LinkedNode*pnew_节点=新LinkedNode(新_数据);
pnew_node->next=NULL;
如果(!长度){
头=尾=新节点;
长度++;
}否则{
tail->next=pnew\u节点;
tail=pnew_节点;
长度++;
}
}
//删除pnode指向的节点
模板
作废LinkedList::删除(LinkedNode*pnode)
{
LinkedNode*ptr=头;
如果(pnode==头部){
head=pnode->next;
}否则{
while(ptr->next!=pnode)
{
ptr=ptr->next;
}    
ptr->next=pnode->next;
}
if(pnode==tail)
tail=ptr;
删除pnode;
长度--;
}
模板
void LinkedList::Show()//打印列表中的所有内容
{
LinkedNode*pnode=头;
while(pnode)
{
std::cout数据下一步;
}

std::cout删除已删除的指针会导致未定义的行为,因此任何情况都可能发生。如果要确保未发生任何情况,请在删除后将指针设置为null。删除
null
不会导致任何错误


<>迭戈:“C++”标准允许删除空指针。编译器在第二次删除它时,不知道指针将包含什么值(即,它可能是空的)。,因此它别无选择,只能允许它符合标准。

我理解的问题是,为什么编译器不抱怨,而是抱怨当你删除某个对象两次时会发生什么。编译器不管理从堆中分配的内存(malloc/free,new/delete)。它只调用正确的例程来删除对象@JonBentley:编译器如何警告运行时操作?@Loki最初的问题清楚地说,“但事实是,当我使用GCC编译程序时,没有发生任何错误。”,所以他寻找的部分答案是,当你尝试删除两次指针时,编译器不会生成错误的原因。我不明白你为什么问我编译器如何警告运行时操作?@JonBentley:因为你对这个问题的解释。如果这是你对这个问题的解释,你应该ting在问为什么。似乎我没有清楚地描述我的问题。我认为当删除两次内存时,程序运行时应该会有一些错误。但事实是,程序运行时没有任何错误。这就是我不理解的地方。@eaglesky这是未定义的行为。就像缓冲区溢出一样,你很可能会因此而损坏内存的一部分,但这并不一定意味着会有任何明显的后果,除非某些代码随后运行,这取决于(现在)内存已损坏。如果在程序完成时没有发生这种情况,那么您将不会注意到任何东西。@eaglesky看看这个问题:@eaglesky:编译器编写者可以让运行时进行检查。但是额外的保护会带来成本。但我为什么要支付成本(我的代码工作正常)只是为了让你的生活更简单。C和C++的一个原则不是强迫人们为他们不想要的东西付费。但是一些编译器确实做了检查。调试模式下的MSVC将使用与发布类似的版本的非常不同的运行时。@ JonBentley,我知道。谢谢你的回复和链接。非类类型(int/float等)通过赋值完成。
#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;
}