operator new/delete of C++

Last Updated: 2023-12-29 03:11:35 Friday

-- TOC --

我们一般使用new来创建对象得到其地址,使用delete销毁对象并释放内存:

T *p = new T{};
delete p;

操作符new干的事情:

  1. 按对象type的size申请内存;
  2. 在此内存上调用对象的constructor;

操作符delete干的事情:

  1. 调用对象的destructor;
  2. 释放对象占用的内存;

我们可以使用operator new/delete来将上面4个动作全部拆分开

#include <iostream>
using namespace std;


struct xyz {
    xyz(void) { cout << "constructor\n"; }
    ~xyz(void) { cout << "destructor\n"; }
};


int main(void) {
    // only allocate memory
    xyz *p { static_cast<xyz*>(operator new(sizeof(xyz))) };

    // placement new
    new(p) xyz{};

    // call destructor explicitly
    p->~xyz();

    // deallocate memory
    operator delete(p);

    return 0;
}

operator new/delete仅仅申请或释放内存,而一般情况下的new/delete,是将其封装起来直接用了。

operator new有三种overload:

// might throw std::bad_alloc
void* operator new (std::size_t size) throw (std::bad_alloc);
// noexcept
void* operator new (std::size_t size, const std::nothrow_t &nothrow_value) noexcept;
// placement noexcept
void* operator new (std::size_t size, void *ptr) noexcept;

前两种overload,涉及代码如何处理new失败的情况

placement new其实就是直接返回传入的指针,但对象的constructor有可能throw,anyway,使用placement new的场景,都不会直接delete对象指针,内存的释放在别处。

对象可以overload创建自己的operator new/delete(前面有一篇总结new/delete的重载,那是全局的overload):

#include <iostream>
#include <cstdlib>
using namespace std;


struct xyz {

    xyz(void) { cout << "* constructor\n"; }
    ~xyz(void) { cout << "* destructor\n"; }

    void* operator new(size_t size) {
        cout << "* overload new in class\n";
        return malloc(size);
    }

    void* operator new(size_t size, const std::nothrow_t &x) noexcept {
        cout << "* overload new without throw in class\n";
        return malloc(size);
    }

    void* operator new(size_t size, void *p) noexcept {
        cout << "* overload placement new in class\n";
        return p;
    }

    void operator delete(void *p) {
        cout << "* overload delete in class\n";
        free(p);
    }
};


int main(void) {
    xyz *a { new xyz{} };
    delete a;

    xyz *b { new(std::nothrow) xyz{} };
    delete b;

    char *c { new char[24]{} };
    xyz *d { new(c) xyz{} };
    delete[] c;

    return 0;
}

输出:

* overload new in class
* constructor
* destructor
* overload delete in class
* overload new without throw in class
* constructor
* destructor
* overload delete in class
* overload placement new in class
* constructor

在输出前加个*,立刻高大上了...

在xyz中overload delete是多余的,只是展示。最后的placement new,不可以调用delete,否则就是double free。

本文链接:https://cs.pynote.net/sf/c/cpp/202209023/

-- EOF --

-- MORE --