C++中operator new与operator delete(重要点进行讲解)

operator new与operator delete函数(重点)

new delete 实现原理

        1. 内置类型

        如果申请的是内置类型的空间,new和malloc,delete和free基本类似,不同的地方是new delete申请和释放的是单个元素的空间,new[]和delete[]申请的是连续空间,而且new在申请空间失败时会抛异常。malloc返回NULL

        2.自定义类型

               * new原理
                        1.调用operator new函数申请空间
                        2.在申请的空间上执行构造函数,完成对象的构造

                *new Array[N]的原理
                        1.调用operator new[]函数,在operator new[]中实际调用operator new函数完成N个对象空间的申请
                        2.在申请的空间上执行N构造函数

                *delete原理
                        1.在空间上执行析构函数,完成对象中资源的清理工作
                        2.调用operator delete数释放对象的空间

                *delete[]原理
                        1.在释放的对象空间上执行N次析构函数,完成N个对象中资源的清理
                        2.调用operator delete[]放空间,实际在operator delete[]中调用operator delete释放空间


new和delete是用户进行动态内存申请和释放的操作符operator new和operator delete是系统提供的全局函数,new在底层调用operator new全局函数来申请空间,delete在底层通过operator delete全局函数来释放空间。

class A
{
    public:
        A()
        {
            cout << "A()" << endl;
        }
        ~A()
        {
            _a = 0;
            cout << "A()" << endl;
        }
    private:
        int _a;
}

int main()
{
    A* p1 = (A*)malloc(sizeof(A));
    A* p2 = new A;
    A* p3 = (A*)operator new(sizeof(A));

    size_t size =2;
    void* p4 = malloc(size *1024*1024*1024*1024);
    cout << p4 << endl;
    
    void* p5 = operator new(size *1024*1024*1024*1024);
    cout << p5 << endl;
    operator delete(p5);

    try{
        void* p6 = operator new(size *1024*1024*1024*1024);
        cout << p6 << endl;
    }
    catch(exception& e)
    {
        cout << e.what() << endl;
    }
    
    return 0;
}

当p4申请空间过大失败会返回0

当p5申请空间过大失败会抛异常

 如果尝试p6这种方法try catch会怎么样呢?bad allocation - 错误分配

 总结:malloc和operator new使用方式都一样,处理错误的方式不一样 可以用try catch 抛出异常

malloc/free   operator new/operator delete   new   delete 这三者有什么区别呢?
 operator new        ==>        malloc+失败抛异常实现
 new                       ==>         operator new + 构造函数
 new比起malloc一样的地方:1、调用构造函数初始化 2、失败了抛异常                                     delete比起free一样的地方:1、调用析构函数清理
operator delete和 free区别,因为释放空间失败直接终止进程。 是因为要跟operatornew对出现才产生

operator new 他的底层函数是这样的

void* __CRTDECL operator new (size_t size) _THROW(_STD bad_alloc)
{
    // try to allocate size bytes
    void *p;
    while((p=malloc(size))== 0)
    if(_callnewh(size)== 0)
    {
        // report no memory
        // 如果申请内存失败了,这里会抛出bad alloc 类型异常
        static const std::bad alloc nomem;
        RAISE(nomem);
    }
    return (p);
}


operator delete他的底层函数是这样的

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 new际也是通过malloc申请空间,如果malloc申请空间成功就直接返回,否则执行用户提供的空间不足应对措施,如果用户提供该措施就继续申请,否则就抛异常。operator delete终是通过free释放空间的。

定位new达式(placement-new)(了解)

定位new达式是在已分配的原始内存空间中调用构造函数初始化一个对象
使用格式:
new(place_address)type或者new(place_address)type(initializer-list)
place_address必须是一个指针,initializer-list是类型的初始化列表
使用场景:
定位new表达式在实际中一般是配合内存池使用。因为内存池分配出的内存没有初始化,所以如果是自定义类型的对象,需要使用new定义表达式进行显示调构造函数进行初始化。

class A
{
    public:
        A(int a=0)
         :_a(a)
        {   
            cout << "A()" << endl;
        }
        ~A()
        {
            cout << "~A()"<< endl;
        }
    private:
        int _a;
};

int main()
{
    A* p1 =new A;
    delete pl;

    // 想模拟上面的行为
    //显示调用了A构造函数和析构函数
    A*p2=(A*)operator new(sizeof(A));
    // 对已经存在的一块空间调用构造函数初始化,定位new/replacement new

    new(p2)A(10); //new空间的指针)类型(参数)参数不是必须
    p2->~A();
    operator delete(p2);

    return 0;
}

常见面试题
malloc/free和new/delete的区别
内存泄漏
什么是内存泄漏,内存泄漏的危害?
内存泄漏分类(了解)
如何检测内存泄漏(了解)
如何避免内存泄漏
如何一次在堆上申请4G的内存?

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我中意你呀丶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值