永发信息网

C++ delete命令的原理是什么?

答案:6  悬赏:80  手机版
解决时间 2021-01-22 18:14
C++ delete命令的原理是什么?
最佳答案
C++ delete命令的原理如下:
  delete也分为两种情况:
  1,简单数据类型(包括基本数据类型和不需要析构函数的类型)。

  [cpp] view plaincopy
  int *p = new int(1);
  delete p;
  delete的汇编码如下:
  [cpp] view plaincopy
  delete p;
  00275314 mov eax,dword ptr [p]
  00275317 mov dword ptr [ebp-0D4h],eax
  0027531D mov ecx,dword ptr [ebp-0D4h]
  00275323 push ecx
  00275324 call operator delete (0271127h)
  分析:传入参数p之后调用operator delete,其源码如下:
  [cpp] view plaincopy
  void operator delete( void * p )
  {
  RTCCALLBACK(_RTC_Free_hook, (p, 0));
  
  free( p );
  }
  RTCCALLBACK默认是空的宏定义,所以这个函数默认情况下就是简单的调用free函数。

  总结:
  delete简单数据类型默认只是调用free函数。
  2,复杂数据类型(需要由析构函数销毁对象)
  代码实例:
  [cpp] view plaincopy
  class Object
  {
  public:
  Object()
  {
  _val = 1;
  }
  
  ~Object()
  {
  cout << "destroy object" << endl;
  }
  private:
  int _val;
  };
  
  void main()
  {
  Object* p = new Object;
  delete p;
  }
  部分汇编码如下:
  [cpp] view plaincopy
  012241F0 mov dword ptr [this],ecx
  012241F3 mov ecx,dword ptr [this]
  012241F6 call Object::~Object (0122111Dh) //先调用析构函数
  012241FB mov eax,dword ptr [ebp+8]
  012241FE and eax,1
  01224201 je Object::`scalar deleting destructor'+3Fh (0122420Fh)
  01224203 mov eax,dword ptr [this]
  01224206 push eax
  01224207 call operator delete (01221145h)
  0122420C add esp,4
  总结:
  delete复杂数据类型先调用析构函数再调用operator delete。
全部回答
首先sizeof并不是万能的,你用sizeof来看大小本来就是错的,用错的东西来解释其它东西,结果肯定是错的
释放内存=。 =
delete之后 aap所指向的内存空间被释放,内存里面可能被赋予空值 可能被系统赋予随机值 ,也有可能被其它资源征用而赋予了它新的有效值 但app仍然指向那个地址 它取出来的值只能是别人的 就像你把房子卖了 你身份证上面的地址仍然是你房子的地址 但里面的内容已经不属于你了
另外在Linux下面运行结果也会不 一样 因为它的内存管理没Windows规范和严谨
如果只用delete释放内存 而不用aap=NULL;就产生了野指针
关于这个问题。我前几天刚好在 Effective C++里看到。
这种问题牵扯到 虚析构函数。
大概是这样的:
比如
A*p=new B;
。。。
delete p;
如果父类的 析构函数不是一个虚函数 。那么delete p这样的行为是不可预测的——无法知道将会发生什么。
C++语言标准关于这个问题的阐述非常清楚:当通过基类的指针去删除派生类的对象,而基类又没有虚析构函数时,结果将是不可确定的(实际运行时经常发生的是,派生类的析构函数永远不会被调用。)
为了避免这个问题,只需要使A的析构函数为virtual。声明析构函数为虚就会带来你所希望的运行良好的行为:对象内存释放时,A和B的析构函数都会被调用。
关于第二个问题 delete p只是释放指针指向的内存所存储的数据,并不会改变指针所保存的地址。因此执行完这个操作可以
设置p=NULL
我执行了delete p,cout<
  • 5楼网友:梦中风几里
  • 2021-01-22 03:43
我们编译出来的程序运行时是和操作系统打交道的,程序中用到的内存都向操作系统申请,在多任务的操作系统下,不允许普通的程序访问未分配的内存。
操作系统手里有一张表,标明内存中的哪些单元被哪个程序占用了,哪些是空闲的(空闲不一定是空值,我们编写的程序如果动态变量没有初始化往往会带有不定值,就是这个缘故),当程序提出申请,它就把空闲的内存分配给程序。程序运行完后操作系统再把分配给的内存标记为空闲,以供其他程序用。
其实我们完全留意到,向磁盘写东西的时候很慢,但把写进了的东西删掉的时候却快得多,原因就在于操作系统删除文件的时候偷懒了,并没有彻底粉碎文件的每一个数据,而是在那张文件分配表上将这个文件所在的区域标记为空闲罢了,多数数据仍然在那里,从而给数据恢复软件留下了后门。
楼主的程序前面会申请空间来存放类A和B的对象。执行到delete就会去内存的堆区将指定的内存单元交还给操作系统。所以必须和new配套使用,否则会酿成严重后果。
我个人的猜测,执行delete只是将它后面变量的地址告诉给操作系统,操作系统把它手里的那张表给改了,但delete掉的指针没有变化,还是原来指向的变量的地址值。可以运行一下这个小程序:
#include
int main(void)
{
int *p;
p=new int;
cout<<(unsigned int)p< delete p;
cout<<(unsigned int)p< p=NULL;
cout< return 0;
}
可以看到,delete前后,指针p的值没有变化。但是如果将2处改为cout<<*p;就要出问题了,操作系统会阻止程序去访问这个地址(表现为访问冲突,Access Violation),因为这个地址已经用delete归还给操作系统了。这时候的指针p叫做悬空状态,也就是野指针,怎么称呼都无所谓。它并没有被销毁,通过重新取其他变量的地址,还可以继续访问*p,但现在不行。
指针实际上是一个无符号整型变量,几乎所有我们碰到的指针,在C++下都是4个字节,因为C++在32位机上将int实现得和long int一样大小。
那么为什么要给指针规定类型呢?我猜测,这一方面是为了访问它指向的对象时确定读取内存单元的长度,比如char型变量占1个字节,int型变量占4个字节,类对象和结构体对象占的长度更加多样化,当定义了一个char型指针p,执行*p时程序只读取一个字节的内容,如果p是int型则*p读取4个连续的字节的内容。还有指针相加减,指针自增自减运算,都可以通过这个来确定一次移动的长度。
另一方面,也防止乱指发生意外吧,C语言中printf和scanf的格式控制串就要用的时候亲自设定,如果设不对运行时就可能出错。
我要举报
如以上问答信息为低俗、色情、不良、暴力、侵权、涉及违法等信息,可以点下面链接进行举报!
大家都在看
推荐资讯