'delete'操作符如何实际在C ++中动态内存分配(堆)中的后台工作?

时间:2017-02-19 10:09:43

标签: c++ c++11 heap-memory delete-operator

我不知道如何在C ++的幕后实际实现“删除”操作符。例如:

class Node{
  int i;
  Node *left,*right;
};

int main()    {
  Node* a = new Node; // somehow the object 'a' is initialised with its data members
  delete a;
}

delete a;在幕后究竟做了什么?就像是 有任何默认的析构函数调用或什么?此外,由于a包含左右指针,对象a->lefta->right是否也被删除了? 核心机器级别会发生什么?

3 个答案:

答案 0 :(得分:0)

它没有被标准定义,所以这个问题无法真正解答,因为标准库的多个实现可以随意实现这些东西。

不,*left*right不会被删除(也就是说它不会像delete left那样做,它只会从内存中删除它们)。就像new Node没有分配额外的内存来设置*left / *right一样。

您尚未明确定义ctor或dtor,因此不会发生任何特殊情况。但是,如果您将定义构造函数/析构函数,那么new& delete。 //编辑:Ofc他们现在被调用,没有用户定义的ctor / dtor,但是没有对你做任何有用的事情。

答案 1 :(得分:0)

当对象的范围结束时,c ++调用默认的析构函数

删除的目的是返回内存(即释放内存),以便计算机可以使用

基本上,当你在运行时使用或其他东西分配内存时,你有责任在任务完成后释放内存 如果您没有释放内存并且指针/对象死亡,那么您使用的内存将被浪费,并且计算机无法使用该内存,这称为内存泄漏。

如果您因内存泄漏而丢失了太多内存,那么堆/免费存储将没有足够的内存来运行您的操作系统,最终您将不得不重启系统

答案 2 :(得分:0)

  

delete a;在幕后究竟做了什么?

可能只是转到存储a指向的对象的免费商店的位置,并将内存标记为可用于将来的分配。 或许如果您已经告诉编译器创建一个可调试的程序版本,那么内存会被额外清零或以其他方式被篡改。

无论编译器做什么,唯一的保证效果是后续delete a或尝试取消引用a会导致未定义的行为。

C ++定义了一种语言,而不是一种实现。

应用 as-if规则,可能根本没有任何事情发生,因为编译器优化已经表明不需要这段代码来创建程序所需的可观察行为。

  

就像是否有任何默认的析构函数被调用或者是什么?

如果你不编写析构函数,那么编译器会自动插入一个public

  

另外,由于a包含leftright指针,对象a->lefta->right是否也被删除?

小心你的措辞。 a->lefta->right 两个对象,就像a->i一样。 C ++比某些其他编程语言更加宽松地使用“对象”这个词。

删除所有三个对象,是的。但是,a->lefta->right每个可能会或可能不会指向其他Node个对象。其他Node个对象不会被删除。

毕竟,他们为什么要这样做?谁说这两个Node个对象只是a->lefta->right指向的?考虑一下:

struct Node{
  int i;
  Node *left,*right;
};

int main()    {
  Node* a = new Node;
  Node l;
  Node r;
  a->left = &l;
  a->right = &r;
  delete a;
}

如果delete以传递方式工作,那么您的代码将尝试删除甚至没有在免费商店中分配的本地对象lr;这将是一场未定义行为的灾难。

  

核心机器级别会发生什么?

C ++没有说明核心机器级别会发生什么。