[英]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 new
和constructor
, delete
操作是否相似?
谢谢
您正在做的是技术上未定义的行为,因此,实际上,就标准而言,任何事情都可能发生。
除此之外,您所看到的实际行为可以轻松推断。 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.