繁体   English   中英

了解C ++中的删除运算符

[英]Understanding delete operator in C++

考虑下面的代码:

#include <iostream>
#include <string>
 using namespace std;

class A{ 
 public: 
     int x; 
 public: 
     A(){x=0;} 
     void fun1(){ 
         cout << "fun1 is called \n"; 
         cout << "Address of this is " << this <<endl; 
         delete this; 
     } 
     void fun2() 
     { 
         cout << "fun2 called \n"; 
     } 
     ~A() 
     { 
             cout << "Object Destroyed" << endl; 
     } 
 }; 

 int main() 
 { 
     A* ptr=new A; 
     cout << "Address of ptr is " << ptr <<endl; 
     ptr->fun1(); 
     ptr->fun2(); 
     return(0); 
 }

输出为:

$ ./TestCPP
Address of ptr is 0x20010318
fun1 is called
Address of this is 0x20010318
Object Destroyed
fun2 called

我的问题是,当我们在fun1()调用delete ,它将破坏this指针所指向的对象,即地址0x20010318 如输出所示,它调用析构函数。 因此,在调用fun1()之后,地址0x20010318的对象被破坏,并且该内存被释放。 那么为什么在输出中可以看到fun2()呢? 仅仅是垃圾价值吗? 我指的是对象不存在,但在由指示位置ptr -> fun2()的定义fun2()仍然存在?

也有人可以解释delete工作原理。 例如调用new调用operator newconstructordelete操作是否相似?

谢谢

您正在做的是技术上未定义的行为,因此,实际上,就标准而言,任何事情都可能发生。

除此之外,您所看到的实际行为可以轻松推断。 fun2是一个非虚拟函数。 编译器将在编译时解决对其的调用。 当对象被销毁时,函数不会被销毁。 当您调用ptr->fun2() ,编译器将仅调用该函数。 由于该函数不依赖任何成员数据,因此输出是完全可预测的(即使就标准而言,不是)。

这是我在null指针上调用非虚拟成员函数的演示。 显然这是错误的,但是它却完全按预期打印了语句: http : //ideone.com/pddnGt

这并不是说代码还不错。 您不应在代码中具有未定义的行为。 在较低的优化级别上,出于调试目的,编译器可能会很好地进行此类检查,并通过错误消息暂停程序或引发异常。

仅仅是垃圾价值吗? 我指的是对象不存在,但在由指示位置ptr -> fun2()的定义fun2()仍然存在?

是的,这是不确定的行为,但是因为实际上没有任何东西可以重复使用内存,所以它似乎可以“正常工作”。 虽然这实际上是一个严重的错误。 (注意: A::fun2()的定义永远不会到任何地方,即代码,而不是数据,因此在程序的整个生命周期中都存在,内存位置ptr的对象停止存在,但是其成员函数的定义不存在')

例如调用new调用operator new和构造函数, delete操作是否相似?

是的,它调用析构函数销毁该位置处的对象,然后调用operator delete释放内存。

如果您的方法不是虚拟的并且不包含对成员的引用,则它可以与某些编译器一起使用,因为汇编中的方法不需要有效的this指针。 无论如何,您必须充满不确定性的举止。

fun1调用delete后,您对fun2的调用是非法的。 C ++不会牵手,因此对于这种“未定义的行为”,任何事情都可以发生,包括适当地称为fun2

实际上, delete调用对象的析构函数,然后释放内存,与new相反。

当您调用delete ,操作系统将被告知该内存不再需要,因此可用于将来的分配。 但是,它不会被自动擦除。

就您而言,在调用fun2之前,其他任何人都不会使用该内存。 没有人试图在两个函数调用之间在堆中分配任何内存。 因此,该对象仍然存在并且从未被篡改。 但是,这并不意味着不可能在两次调用之间分配内存(例如,可能会触发中断,并且在处理中断期间可能会分配内存)。 因此,您永远不要这样做。 :)

当您从类中调用非虚拟函数时,该函数

class A { public: void function(int k) { ... } };

将被写成类似

void __A_function(A* this, int k);

如果您的函数不包含this指针,则它将被称为标准函数,而忽略this参数。

我可以预测的另一件事是,即使你这样做

class A
{
private:
  int k;
public:
  A() : k(10) {}
  void function() { printf("%d\n",k); }
};

A* ptr=new A;
delete ptr;
ptr->function();

在大多数情况下,它将打印出10张。 因为来自new的内存尚未清除。

我将推荐Inside C ++ Object Model来对此进行详细了解。

成员函数在编译时解析。

您可以执行以下操作:

A* ptr = NULL;
ptr->yourFunc();

只要您不访问对象(及其VTable,因此您不想调用方法)中的数据存储,它将起作用。

'this'的值为null,可以。 但是取消对任何内容的重新配置将导致段错误。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM