delete this

【c++】析构函数中delete this指针 在析构函数中delete this指针,会产生什么样的结果呢? 先看看下面这段代码,想想运行结果。 #include using namespace std; class A { public: A() { cout<<"A()"<<endl; } ~A() { cout<<"~A()"<<endl; delete this; } }; int main() { 阅读详情
delete this触发

a. 析构

b. ::operator delete(void*)

delete 之后,仍然可以进行成员函数、成员变量的操作,但是正确性不可靠。

class Test {
  public:
  Test():mm(111) {/* delete this;*/ cout << mm <<endl;}
  ~Test() { cout <<"dect" <<endl; }
  void aaa() {    delete this;  };  
  void bbb() {  cout << "bbb" <<endl;  }
  void ccc() {    cout << "ccc:" << mm <<endl;  }
  int mm; 
};

int main(int argc, char *argv[]) {

  Test *aa = new Test;
  aa->bbb();
  aa->ccc();
  aa->aaa();
  return 0;
}


In order to understand "delete this" :


First Step - dive into "delete p"

delete p执行了哪些步骤?
delete p
是一个两步的过程:调用析构函数(释放类里边涉及new的内存),然后释放内存(类本身占的内存)。


delete p产生的代码看上去是这样的(假设是Object*类型的):

delete原语可以看作如下这样一个过程:
p->~Object();
p->operator delete(p);

p->~Object()语句调用p指向的Object对象的析构函数。
p->operator delete(p)
语句调用对象p的内存释放原语 void operator delete(void* p)。如果没有实现该方法,将调用系统的内存释放原语::operator delete(ptr)做释放该对象内存的操作。当然细节上并不这么简单,我们最后的实验部分会详细讨论。

 

Second Step - "delete this"

成员函数调用delete this合法吗?
只要你小心,一个对象请求自杀(delete this),是可以的。

以下是我对“小心”的定义:

你必须100%的确定,this对象是用 new分配的(不是用new[],也不是用定位放置 new,也不是一个栈上的局部对象,也不是全局的,也不是另一个对象的成员,而是明白的普通的new)。

你必须100%的确定,该成员函数是this对象最后调用的的成员函数。

你必须100%的确定,剩下的成员函数(delete this之后的)不接触到this对象任何一块(包括调用任何其他成员函数或访问任何数据成员)。

你必须100%的确定,在delete this之后不再去访问this指针。换句话说,你不能去检查它,将它和其他指针比较,和NULL比较,打印它,转换它,对它做任何事。

自然,对于这种情况还要习惯性地告诫:当你的指针是一个指向基类类型的指针,而没有虚析构函数时(也不可以delete this)。

注意:因为是在类成员函数里面delete this的,所以在此语句以后,不能访问任何的成员变量及虚函数(调用虚函数必须对象实例存在以检查类型),否则一定非法。

上面所说的在执行时不一定会报错,但尽量不要这么做。

Some test examples:

析构函数本身是不会释放内存的,
除非在析构函数里面显示的使用delete操作符
.

在对类指针使用delete时,实际发生了两个步骤。

A:
先是调用该类的析构函数,以做数据成员的释放工作,以及一些finish code,这一切由程序员自己定义。

B:
然后再调用operator delete(void*)释放该对象实例的内存数据。这是一个对象在消亡之前的所做的最后动作。一般不要override这个函数,如果要,务必记住最后调用系统的::operator delete真正释放该对象所占用的内存。

一般来说,内存释放释放的只能是数据段的内容(包括堆和栈,但释放栈上的内存由系统进行),而代码段的内存,除一些病毒攻击等非正常强行改写手段外,在内存中是永远不会释放/改变的,直到程序结束,因此在内存释放后也是可以访问的。所以,一般所谓的释放内存delete操作,是在数据段进行的释放。

可以试试下面的代码
Example 1:两步操作

class x {
public :
        x(){}
        ~x() {
                printf("%s/n","~x()");
        }
};

void main() {
        x* p=new x;
        ::operator delete(p); //调用delete内存释放原语,不会调用~x(),如果确实调用了系统::operator delete,就没有内存泄露(也可能由用户函数覆盖)

        delete p; //~x()依然会执行,operator delete中将会报错(最后将讨论)

}


Example 2: override
重写的operator delete

class x {
public :
        x(){
        }
        ~x() {
                printf("~x()/n");
                //delete p; //这里若进行此操作则会陷入嵌套

        }
        void operator delete(void * ptr) {
                printf("x::delete()/n");
        }
};

void main() {
        x* p=new x;
        delete p; //依次调用p的~x()和
operator delete
        delete p; //不会报错,因为"operator delete" override了系统函数,没有进行::operator delete(this)操作。

        delete p; //同理依然不会报错

}


Example 3:
默认的operator delete

class x {
public :
        x(){
                //delete p; //构造时delete不会报错,只要确保以后不会用到该实例(包括delete p)。

        }
        ~x() {
                printf("~x()/n");
        }
};

void main() {
        x* p=new x;
        delete p; //依次调用p的~x()和operator delete(其中调用了系统的::operator delete)

        //delete p; //报错,这里没有override,对象调用的是系统的::operator delete

}

进一步分析:

让我们看一下系统::operator delete的内部实现(in dbgdel.cpp):
void operator delete(
        void *pUserData
        )
{
        _CrtMemBlockHeader * pHead;

        RTCCALLBACK(_RTC_Free_hook, (pUserData, 0));

        if (pUserData == NULL)
            return;

        _mlock(_HEAP_LOCK);/* block other threads */
        __TRY

           /* get a pointer to memory block header */
            pHead = pHdr(pUserData);

            /* verify block type */
            _ASSERTE(_BLOCK_TYPE_IS_VALID(pHead->nBlockUse)); //检查该段内存是否被程序占用。一般出现的如果内存已经释放了,又执行内存释放操作,这里就会报错

            _free_dbg( pUserData, pHead->nBlockUse );

        __FINALLY
            _munlock(_HEAP_LOCK);
/* release other threads */
        __END_TRY_FINALLY

        return;
}
如果在里面设置断点,无论是直接调用::operator delete还是类似delete p调用对象的operator delete,如果没有人为override,都会进入这个函数,进行释放内存的操作。因此一个C++的类其实可以看做是有一个类似java的Object在内部进行操控:

class object {
public :
        object() { }
        ~object() { }
        void operator delete(void *ptr) {
                ::operator delete(ptr);
        }
};

delete原语看起来会是如下的样子:
p->~object();
object::operator delete(p);

因为代码段的内存是不会被释放的,因此无论对象p的内存有没有释放,这两个语句都会执行,不会因为p没有指向任何存在的对象而报错,只是在最后执行到::operator delete的时候,才会在执行_ASSERTE(_BLOCK_TYPE_IS_VALID(pHead->nBlockUse))的时候报错。

Example 4:代码段不会被释放
class x {
public :
    x(){printf("x()/n"); }
    ~x() {
        printf("~x()/n");
        operator delete(this);
        //以下并不会报错

        int n=~get(34);//
返回-6(~5)
        x(); //会连带调用
x()->~x()->operator delete
    }
    void operator delete(void *p) { //这其实是一个静态函数,成员函数调用不能放在里面

        ::operator delete(p);
        printf("x::delete()/n");
    }
    int get(int ) { //注意这个申明是合法的

        printf("x::get()/n");
        return 5;
    }
};

int main()
{
    x* p=new x;
    x::x(); //合法的,会连带调用x()->~x()->operator delete,但会因为具体对象不存在而报错

    //p->x(); //调用非法,编译不通过
    delete p;
    int num = p->get(1); //不会报错,返回
5
}

Example 5:释放内存只释放数据段
class x {
public :
    int n;
    x() {
        printf("x()/n");
        n=5;
    }
    ~x() {
        printf("~x()/n");
    }
    void operator delete(void *p) { //这其实是一个静态函数,成员函数调用不能放在里面

        ::operator delete(p);
        printf("x::delete()/n");
    }
    int get(int ) {
        printf("x::get()/n");
        return n;
    }
    void test() {
        delete this;
        //以下并不会报错

        int n=this->get(34); //会得到一个非法值,不是5
    }
};

int main()
{
    x* p=new x;
    p->test();
    delete p;
    int num = p->get(1); //会得到一个非法值,不是
5
}


this指针和delete this 文章目录this指针的作用this指针是否可以为空delete this合法吗 this指针的作用   this指针是指向类对象的指针,在类的成员函数中通过this指针这个隐式参数来访问调用它的对象。当我们调用一个成员函数时,编译器会把对象的地址传给成员函数的隐式形参this。this指针可以区分静态成员函数和外部函数(如静态函数),后者没有。   为什么要引入this指针。由于每个对象都有其状态... 阅读详情

相关推荐

图像去畸变(相机成像、畸变模型)

首先通过上一步相机标定得到畸变参数和相机内参,同时,由于图像去畸变都是在归一化相机坐标系下进行的,而图像都是像素坐标,所以需要先通过相机内参矩阵将图片上的像素点从像素坐标系转变到归一化坐标系,再通过畸变参数在归一化坐标上进行去畸变的操作。由于畸变是发生在世界点通过透镜投影到相机坐标系这个过程中的,所以去畸变操作是在相机坐标系下进行的。(如图,Pd即为畸变后成像点)3.读取图像和各个参数,调用去畸变函数(opencv自带的cv.undistort函数),就可以完成对图像的去畸变处理,进而得到去畸变的图像。

lm5688jjupm1n28的博客 1051

C++中的"delete this"

引子 C++中delete能否用于栈对象 C++中”delete this”会出现什么问题 C++中”delete this”有什么规避方法 C++中delete能否用于栈对象在大家的印象中delete只能用于new出动态内存对象,我们使用了g++/Clang++/MSVC来测试delete栈对象的情况。测试代码如下:int main() { int num = 10; int* p

电影旅行敲代码 5749

基于树莓派5的AR头显开发:从硬件选型到Unity整合全解析

增强现实(AR)技术通过将虚拟信息叠加到真实世界,为用户提供沉浸式交互体验。其核心原理依赖于计算机视觉进行环境感知与空间定位,并结合实时3D渲染实现虚实融合。在工程实践中,嵌入式平台因其低成本、低功耗特性,成为探索AR应用边界的重要载体。本项目以树莓派5为核心,通过集成OpenCV进行ArUco标记识别实现精准空间定位,并利用MediaPipe完成手势交互,最终在Unity引擎中完成虚实场景的实时渲染与融合,为开发者提供了一个完整的、可亲手实践的AR系统开发方案。

weixin_32430941的博客 254

避开C++中的陷阱:浅析delete this的使用与危害

内存管理之后,内存空间被释放,但这并不意味着内存空间立即返回给系统。实际上,操作系统的内存管理策略可能会导致这段内存暂时未被系统收回,所以它的内容并不稳定,可能会是随机数据。访问这样的内存区域,可能会导致一些未定义的结果。在成员函数中调用在绝大多数情况下是不安全的,会导致对象变得不可用,任何对此对象的引用操作都是未定义的行为。由于操作系统的内存管理,已释放内存可能暂时可访问,但这段内存是随机且不稳定的,使用会导致未定义行为。在析构函数中调用。

m0_72877724的博客 1334

STM32解析航模遥控器的PPM信号

使用STM32对航模遥控器的PPM信号进行解析

qq_44343584的博客 9734

树莓派上基于ONNXRuntime与Qt的C++模型部署实战指南

本文详细介绍了在树莓派上使用ONNXRuntime与Qt进行C++模型部署的完整流程。从环境配置、依赖安装到交叉编译优化,再到Qt界面集成与ARM架构性能调优,提供了实战指南和常见问题解决方案,帮助开发者高效完成边缘设备上的AI应用部署。

ik6789012的博客 339

对象析构谈—— delete this 的使用及注意事项

In order to understand "delete this" : First Step - dive into "delete p" delete p 执行了哪些步骤? delete p 是一个两步的过程:调用析构函数(释放类里边涉及new的内存),然后释放内存(类本身占的内存)。 delete p产生的代码看上去是这样的(假设是Object*类型的): d

把握自己。 1万+

华为 MetaERP 集成盘古大模型、天筹 AI 求解器等生成式 AI 相关技术能力,结合华为云数智融合平台的支撑,在供应链预测中围绕需求预测、物料匹配

华为 MetaERP 集成盘古大模型、天筹 AI 求解器等生成式 AI 相关技术能力,结合华为云数智融合平台的支撑,在供应链预测中围绕需求预测、物料匹配、风险预警等核心场景开展实践,大幅提升了供应链预测的精准度与效率,以下是具体实践内容及成效: 动态需求预测,降低库存偏差华为供应链涉及数万种采购物料,物料清单层级高,且市场需求波动大。MetaERP 集成华为云 ModelArts 等工具构建专属动态需求预测模型,融合深度学习算法,纳入市场趋势、历史销售、产能数据等多维度信息进行综合预测。在华为自身供应链应

金牌架构师 700

C++面试题:在成员函数中delete this 有什么问题?

在C++编程语言中,delete this 是一种不常见且潜在危险的做法,它允许对象在成员函数内部自行销毁自己。虽然在某些特定的情况下使用 delete this 可能是合理的,但大多数情况下,这种做法会导致代码难以维护、理解,并且容易引发各种问题。

CppPlayer 940

【电容/电感】电路板会“滋滋”的响,我们称它为啸叫

一、啸叫的起源 大部分硬件工程师应该都遇到过,PCBA上电后出现“滋滋滋”的叫声,其声响或大或小,或时有时无,或深沉或刺耳,或变化无常者皆有。该现象我们称为“啸叫”,一般分为电感啸叫和电容啸叫。

云轩阁 6万+

【WRFDA教程第一期】运行观测预处理程序(OBSPROC)

运行观测预处理程序(OBSPROC)

WW、forever的博客 1893

关于delete this

在类的成员函数中能不能使用delete this? 答:能!在某些设计模式中需要赋予对象自我销毁的能力,这个时候就可以使用delete this将该对象的this指针进行删除,但是需要确定的是不能在访问该对象的数据成员,或需要调用访问这些成员的函数,虽然还是可以访问,但数据已经是不安全的。 使用delete this的注意事项: 1.通常情况下delete this 往往是跟对象指针一起使用

bemf168的博客 3529

YOLOv13|损失函数优化篇:Focal EIOU 保持良好性能的同时,提供更高效的计算和更稳定的训练过程-包源码

Focal IoU与EIoU:目标检测中的损失函数优化 摘要:本文深入探讨了目标检测中两种重要的边界框回归损失函数优化方法。Focal IoU借鉴Focal Loss思想,通过(1-IoU)^γ因子调节损失权重,使模型更关注难样本(低IoU预测框),有效解决了传统IoU Loss对难易样本权重相同的问题。EIoU则在CIoU基础上改进,通过简化长宽比计算、分离宽高损失项,提升了计算效率和训练稳定性。两种方法分别从样本权重分配和损失函数结构优化角度,显著提升了目标检测性能,为实际应用提供了更高效的解决方案。文

FJN110的博客 1864

C++的delete this合法吗?

这是C++标准基金会(isocpp)的答案:来源https://isocpp.org/wiki/faq/freestore-mgmt#delete-this Is it legal (and moral) for a member function to say delete this? As long as you’re careful, it’s okay (not evil) for an object to commit suicide (delete this). Here’s how..

liji_digital的博客 721

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

delete this 可行性分析

在类的成员函数中能不能调用dudelete this?答案是肯定的,能调用,而且很多老一点的库都有dao这种代码。假设这个成员函数名字叫release,而delete this就在这个release方法中被调用,那么这个对象在调用release方法后,还能进行其他操作,如调用该对象的其他方法么?答案仍然是肯定 的,调用release之后还能调用其他的方法,但是有个前提:被调用的方法不涉及这个对象的数据成员和虚函数。 根本原因在于delete操作符的功能和类对象的内存模型。当一个类对象声明时,系统会为其分配内

flf1234567898的博客 335

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

在类中调用delete this问题

很多时候,一些定义在类内的变量的生命周期在类外并不是很好的掌控,这样就很容易造成内存泄漏得到问题 比如以下代码: class Test { public: void foo(); private: char *p; }; void Test::foo() { p = new char[50]; } int main() { Test t1; t1....

kuimzzs的博客 9612

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

delete this的用法

In order to understand "delete this" : First Step------dive into "delete p" delete p 执行了哪两个步骤? delete p 是一个两步的过程:调用析构函数,然后释放内存。delete p产生的代码看上去是这样的(假设是Fred*类型的): // 原始码:delete p; if (p != NULL)

face_look的专栏 594

delete this 的用处

In order to understand "delete this" : First Step------dive into "delete p" delete p 执行了哪两个步骤? delete p 是一个两步的过程:调用析构函数,然后释放内存。delete p产生的代码看上去是这样的(假设是Fred*类型的): // 原始码:delete p; if (p != NULL)

享受开发技术,享受计算机科学 674

C++ 类自杀 delete this

首先摆明观点,可使用,但必须是new产生的对像,注意,这里数组也不可以。 在C++ FAQ看到该问题的阐述,原文如下: [16.15] Is it legal (and moral) for a member function to say delete this? As long as you’re careful, it’s OK for an object to commit suicid...

迪迦 • 奥特曼 927

Qt QCloseEvent中delete this的bug

目录 一、现象 二、解决方法 三、原理 1、概述 2、源码 3、分析 四、总结 一、现象 最近修改别人代码时,发先在QCloseEvent中delete this 的代码会发生崩溃现象。 void MyWidget::closeEvent(QCloseEvent *event)//此函数在QWidget关闭时执行 { delete this;//会发生崩溃 } 二、解决方法 使用deletelater函数解决 void MyWidget::closeE...

kupePoem的专栏 1348

C++ 中可以使用 delete this 吗?深入解析自删除的可行性与风险

实践 | 说明 || 优先使用智能指针 |是更安全的选择 || 私有析构函数 | 防止栈上创建对象和意外 delete || 提供工厂方法 | 统一对象创建方式,确保使用 new || 调用后立即返回 |后不应有任何访问对象成员的操作 || 文档化风险 | 明确注释哪些函数可能销毁对象 || 避免在复杂调用链中使用 | 调用者很难判断对象是否仍然存活 |严格的前置条件:对象必须通过new分配、调用后不能访问任何成员、不能存在其他指向该对象的指针。任何一个条件不满足,都将导致未定义行为。

✨ 欢迎来到【Seal ^_^ 的优快云博客】!✨ 738
上一篇: 获取本机的主机名和ip地址
下一篇: boost::asio 的同步方式
dodo_check
博客等级 码龄19年 29粉丝 21原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值