c++类重载operator new和delete运算符(一)

2018-07-29  本文已影响11人  dnsir

1 背景

在c++项目开发中,极少数情况下就需要重载newdelete运算符,比如:

  1. 使用内存池
  2. 定位内存泄露等

再看seastar项目中class packet对类进行了重载:

class packet {
...
      void* operator new(size_t size, size_t nr_frags = default_nr_frags) {
            assert(nr_frags == uint16_t(nr_frags));
            return ::operator new(size + nr_frags * sizeof(fragment));
        }
        // Matching the operator new above
        void operator delete(void* ptr, size_t nr_frags) {
            return ::operator delete(ptr);
        }
        // Since the above "placement delete" hides the global one, expose it
        void operator delete(void* ptr) {
            return ::operator delete(ptr);
        }
...
};

当然这里重载new不是以上两种需求而是特殊内存分配场景。

2 重载示例

2.1 最基本重载new和delete

#include <iostream>

struct X {
    X(){}

    static void *operator new(std::size_t sz, int n)
    {
        std::cout << "custom placement new called, size = " << sz << "|n = " << n << std::endl;
        return ::operator new(sz);
    }

    public:
        int a; //4字节
        int b; //4字节
};

int main()
{

    X *p1 = new(4) X;
    delete p1;
    // std::cout << "----default version---" << std::endl;
    // X *p2 = new X;
    // delete p2;
    return 0;
}

在这个示例中仅仅重载了new,并没有重载delete,下面我们试着重载delete

#include <iostream>

struct X {
    X(){}

    static void *operator new(std::size_t sz, int n)
    {
        std::cout << "custom placement new called, size = " << sz << "|n = " << n << std::endl;
        return ::operator new(sz);
    }

    static void operator delete(void* ptr, int n)
    {
        std::cout << "custom delete called1" << std::endl;
        return ::operator delete(ptr);
    }
    public:
        int a; //4字节
        int b; //4字节
};

int main()
{

    X *p1 = new(4) X;
    delete p1;

    return 0;
}

编译竟然报错了:

error: no suitable ‘operator delete’ for ‘X’
delete p1;

也就是说delete p1调用的是默认函数,于是增加以下代码:

    static void operator delete(void* ptr)
    {
        std::cout << "default placement delete called." << std::endl;
        ::operator delete(ptr);
    }

输出结果是:

custom placement new called, size = 8|n = 4
default placement delete called

2.3 默认new函数处理

因为重载了new operator,所以也必须定义默认的new函数,否则当new一个默认的对象时会出错,如以下main函数:

int main()
{

    X *p1 = new(4) X;
    delete p1;

    std::cout << "----default version---" << std::endl;
    X *p2 = new X;
    delete p2;
    return 0;
}

编译时会报错,提示没有默认的new函数

2.4 完整版本

  1. 下载源码链接
  2. 重载new和delete实现内存池
上一篇下一篇

猜你喜欢

热点阅读