美文网首页
c++类重载operator new和delete运算符(一)

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

作者: dnsir | 来源:发表于2018-07-29 11:04 被阅读11次

    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实现内存池

    相关文章

      网友评论

          本文标题:c++类重载operator new和delete运算符(一)

          本文链接:https://www.haomeiwen.com/subject/alrzmftx.html