new与delete的使用及原理,C++内存管理

内存管理

1.malloc1

2.new delete关键字2

3.operator new和operator3

4.定位new4

5.malloc free和new delete异同5


  1. malloc calloc realloc free函数

    内存区域划分

    在C语言中常用malloc calloc realloc free开辟和释放位于堆上的动态内存。

    malloc:

    void* malloc (size_t size);
    

    calloc:

    void* calloc (size_t num, size_t size);
    

    realloc:

    void* realloc (void* ptr, size_t size);
    

    free:

    void free (void* ptr);
    


    malloc calloc realloc函数都需要手动检查返回值确认空间是否开辟成功。 ↩︎

  2. new delete关键字

    在C++中一般使用new delete关键字代替malloc calloc realloc free函数。

    new和delete语法

    new和delete,new[]和delete[]一定要配套,否则可能引起编译错误。new[]申请的是连续的空间。

    对于内置类型来说,new/delte和malloc/free组合使用起来没有太大区别,只是省去了强制类型转换,让代码更加直观。

    对于自定义类型来说,new/delte比malloc/free要方便很多,new可以在开辟空间后自动调用构造函数,delete可以在调用析构函数后清理对象的空间。

    new的实现原理

    1.call operator new()函数

    2.call stack::stack调用stack类的构造函数

    delete的实现原理

    1.call stack::~stack调用stack类的析构函数

    2.call operator delete()函数

    方括号实现原理

    new T[N]的原理

    1. 调用operator new[]函数,在operator new[]中实际调用operator new函数完成N个对象空间的申

    2. 在申请的空间上执行N次构造函数

      delete[]的原理

    3. 在释放的对象空间上执行N次析构函数,完成N个对象中资源的清理

    4. 调用operator delete[]释放空间,实际在operator delete[]中调用operator delete来释放空间

    ↩︎
  3. operator new和operator delete函数

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

    operator new()

    void *__CRTDECL operator new(size_t size) _THROW1(_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 new函数首先通过malloc函数开辟空间,假如开辟失败会抛出bad_alloc 类型异常,可以在函数外用try/catch捕获异常。

    operator delete()

    void operator delete(void *pUserData)
    {
    _CrtMemBlockHeader * pHead;
    RTCCALLBACK(_RTC_Free_hook, (pUserData, 0));
    if (pUserData == NULL)
    return;
    return;
    _mlock(_HEAP_LOCK); 
    __TRY
    pHead = pHdr(pUserData);
    _ASSERTE(_BLOCK_TYPE_IS_VALID(pHead->nBlockUse));
    _free_dbg( pUserData, pHead->nBlockUse );
    __FINALLY
    _munlock(_HEAP_LOCK); 
    __END_TRY_FINALLY
    return;
    }
    

    operator delete 最终也是通过free来释放空间的

    operator new和delete的类专属重载

    当该类局部和全局都有operator new和delete时,对象优先调用自己类里面的operator重载函数。

    下面代码演示了,针对链表的节点ListNode通过重载类专属 operator new/ operator delete,实现链表节点使用内存池申请和释放内存,提高效率。

    struct ListNode
    {
    ListNode* _next;
    ListNode* _prev;
    int _data;
    void* operator new(size_t n)
    {
    void* p = nullptr;
    p = allocator<ListNode>().allocate(1);
    cout << "memory pool allocate" << endl;
    return p;
    }
    void operator delete(void* p)
    {
    allocator<ListNode>().deallocate((ListNode*)p, 1);
    cout << "memory pool deallocate" << endl;
    }
    };
    class List
    {
    public:
    List()
    {
    _head = new ListNode;
    _head->_next = _head;
    _head->_prev = _head;
    }
    ~List()
    {
    ListNode* cur = _head->_next;
    while (cur != _head)
    {
    ListNode* next = cur->_next;
    delete cur;
    cur = next;
    }
    delete _head;
    _head = nullptr;
    }
    private:
    ListNode* _head;
    };
    int main()
    {
    List l;
    return 0;
    }
    
    ↩︎
  4. 定位new

    使用格式:

    new (place_address) type或者new (place_address) type(initializer-list)
    

    定位new表达式在实际中一般是配合内存池使用。因为内存池分配出的内存没有初始化,所以如果是自定义类型的对象,需要使用new的定义表达式进行显示调构造函数进行初始化。

    调用构造函数的三种方法

    1.成员初始化

    2.使用new关键字

    3.使用定位new(可以令已经初始化的成员再次调用构造函数) ↩︎

  5. malloc free和new delete异同

    malloc/free和new/delete的共同点是:

    都是从堆上申请空间,并且需要用户手动释放。

    不同的地方是:

    1. malloc和free是函数,new和delete是操作符
    2. malloc申请的空间不会初始化,new可以初始化
    3. malloc申请空间时,需要手动计算空间大小并传递,new只需在其后跟上空间的类型即可
    4. malloc的返回值为void*, 在使用时必须强转,new不需要,因为new后跟的是空间的类型
    5. malloc申请空间失败时,返回的是NULL,因此使用时必须判空,new不需要,但是new需要捕获异常
    6. 申请自定义类型对象时,malloc/free只会开辟空间,不会调用构造函数与析构函数,而new在申请空间
      后会调用构造函数完成对象的初始化,delete在释放空间前会调用析构函数完成空间中资源的清理
    ↩︎
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值