C++中的new和delete真的复杂吗?(下)

C++中的new和delete真的复杂吗?(上)中为大家介绍了与new有关的知识,这篇文章接着上一篇为大家讲解delete关键字。

前言

在上一篇文章中我们了解到new关键字的基本功能通过operator new与构造函数实现,而operator new除调用malloc分配内存外还调用new_handler来达到对内存整理与重分配,并通过抛出异常的方式来提示内存分配错误,那delete的执行细节又是怎样呢?我们一起来看一看!

1.delete关键字

C++ primer plus中如此描述delete关键字:
当需要内存时,可以使用new来请求。另一方面是delete运算符,它使得在使用完内存后,能够将其归还给内存池。

那么delete到底是如何归还内存的呢?
  我们先来看一下delete简单类型时的情况:

            delete a;
01061278  push        eax  
01061279  call        dword ptr ds:[10630ACh]    // delete调用了 operator delete
0106127F  add         esp,8  

上面是delete执行时VS Release模式下的汇编码,有了new的经验大家应该可以猜到call语句的去向了。

void operator delete( void * p )
{
    RTCCALLBACK(_RTC_Free_hook, (p, 0));

    free( p );
}

继续跟踪我们发现与operator new相比较operator delete 相当的简洁,这里有一个RTCCALLBACK的宏定义,其原型我们可以在 rtcsup.h找到:

# define RTCCALLBACK(a, b)

很明显他是一个空的宏定义,这就意味着对于简单类型operator delete只是简单的调用了free

如果读者在VS2010之后版本的编译器中使用delete时可能会发现delete后指针指向的地址发生了变化,这是因为在VS2010及之后的版本中加入了叫做safe delete特性,将delete后的指针指向特定安全值防止使用野指针或重复delete。如果用户使用delete后的指针,或重复delete一个指针,程序会抛出异常。

注意safe delete功能可以通过将指针赋NULL来实现但微软并没有这样做,因为delete一个空指针在C++中是
合法的,并不会抛出异常。在VS中delete一个空指针也不会触发safe delete。

2.delete复杂类型

class MyObject
{
public:
    int a;
    MyObject()
    {
        a = 1;
    }
    ~MyObject()
    {
        a = 0;
    }
};

delete在DEBUG模式下的汇编码。

            MyObject::`scalar deleting destructor':
003E2800  push        ebp  
003E2801  mov         ebp,esp  
003E2803  sub         esp,0CCh  
003E2809  push        ebx  
003E280A  push        esi  
003E280B  push        edi  
003E280C  push        ecx  
003E280D  lea         edi,[ebp-0CCh]  
003E2813  mov         ecx,33h  
003E2818  mov         eax,0CCCCCCCCh  
003E281D  rep stos    dword ptr es:[edi]  
003E281F  pop         ecx  
003E2820  mov         dword ptr [this],ecx  
003E2823  mov         ecx,dword ptr [this]  
003E2826  call        MyObject::~MyObject (03E1424h)   //先调用析构函数
003E282B  mov         eax,dword ptr [ebp+8]  
003E282E  and         eax,1  
003E2831  je          MyObject::`scalar deleting destructor'+3Fh       (03E283Fh)  
003E2833  mov         eax,dword ptr [this]  
003E2836  push        eax  
003E2837  call        operator delete (03E1122h)   // 后调用operator delete

从上面汇编执行过程我们就可以看出,delete在复杂类型情况下执行与new相反,先调用析构函数,在执行operator delete 归还内存。

3.delete的执行过程:

相对于new运算符delete的执行过程可以说相当简明:

delete -> 析构函数(如果有) -> operator delete -> RTCCALLBACK空宏定义 -> free

4.重载operator delete

operator new一样,我们也可以重载operator delete

class MyObject
{
public:
    int a;
    MyObject()
    {
        a = 1;
    }
    ~MyObject()
    {
        a = 0;
    }
    void operator delete(void *p)
    {
        std::cout << "delete MyObject" << std::endl;
        return ::operator delete(p);
    }
};

这里要注意由于operator new和operator delete 都是静态函数,如过将其重载为非Public类型将导致无法使用newdelete,当然也可以使用这一特性构造出特殊的代码。

5.delete[]

            delete[] m;
00B4393D  mov         eax,dword ptr [m]  
00B43940  mov         dword ptr [ebp-0E0h],eax  
00B43946  mov         ecx,dword ptr [ebp-0E0h]  
00B4394C  mov         dword ptr [ebp-0ECh],ecx  
00B43952  cmp         dword ptr [ebp-0ECh],0  
00B43959  je          main+0F0h (0B43970h)  
00B4395B  push        3  
00B4395D  mov         ecx,dword ptr [ebp-0ECh]  
00B43963  call        MyObject::`vector deleting destructor' (0B414B0h)    
//delete[] 使用 vector deleting destructor 来释放数组

delete[]使用vector deleting destructor 来释放数组,而复杂类型使用数组头指针储存数组长度,使用delete[]没有问题,但使用delete就变成了简单释放头指针指向的内存这会造成内存泄露。
  而简单数据类型则完全没有问题,也就是说:

int * a = new int[15];
delete a;

这是可行的,具体为什么可行就要到free内部找答案了。读者可自行探究。虽然可行,但从习惯上来说还是建议使用delete[] 释放 int[]申请的内存。

newdelete还有很多重载用法,这里就不再向大家一一列举了,希望大家喜欢我的文章!
            简书●null122转载请注明出处

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,835评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,598评论 1 295
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,569评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,159评论 0 213
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,533评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,710评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,923评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,674评论 0 203
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,421评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,622评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,115评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,428评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,114评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,097评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,875评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,753评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,649评论 2 271

推荐阅读更多精彩内容