[C++] 重载new和delete——控制内存分配

 
1、new和delete表达式的工作机理
    
1)new表达式实际执行了三步
string *sp=new string("aaaa");
string *arr=new string[10];//string采用默认初始化
     a、调用一个名为operator new(或者operator new[])的标准库函数,分配一块足够大的、原始的、未命名的内存空间,来准备存储对象或者对象的数组;
     b、编译器运行相应的构造函数构造这些对象,在这里运行的是string的构造函数;
     c、返回一个指向该对象或者对象数组的指针。
 
2)delete执行了两步操作:
delete sp;
delete []arr;
      a、对sp或者arr所指的数组中的元素执行相应的析构函数;
      b、编译器调用名为operator delete或者operator delete[]的标准库函数释放内存空间。
 
所以,想要控制内存分配,需要重载标准库函数中的operator new和operator delete函数,可以在类中重载,也可以在类外(全局)重载;使用作用域运算符::可以忽略类中的函数,直接执行全局作用域中的版本,::operator new,::operator delete。
 
2、标准库函数中的operator new 和operator delete
#ifndef _NEWANDDELETE_H_
#define _NEWANDDELETE_H_
#include<new>
#include<cstdlib>
using namespace std;

class NewAndDelete {
public:
    /**
    * 以下是标准库函数中的operate new和operator delete
    * 前面4个会抛出异常,后面4个不会抛出异常
    * 这几个运算符函数是隐式静态的,因为operator new在构造对象之前,用来分配空间;operator delete在对象销毁之后,用来释放空间
    * operator new 或者operator new[]的返回类型必须是void*,第一个形参类型必须是size_t并且没有默认实参,size_t代表要分配的空间的大小
    * operator delete或者operator delete[]返回类型必须是void,第一个形参类型必须是void*,用指向待释放内存的指针来初始化
    * 这两个函数的行为与allocator类中allocate()和deallocate()很类似
    */
    static void *operator new(size_t);
    static void *operator new[](size_t);
    static void operator delete(void*)noexcept;
    static void operator delete[](void*)noexcept;

    static void *operator new(size_t, nothrow_t&)noexcept;
    static void *operator new(size_t, nothrow_t&)noexcept;
    static void operator delete(void*, nothrow_t&)noexcept;
    static void operator delete[](void*, nothrow_t&)noexcept;
};

//实现示例——使用malloc和free
void* NewAndDelete::operator new(size_t size) {
    if (void *mem = malloc(size))
        return mem;
    else
        throw bad_alloc();//抛出异常
}
void NewAndDelete::operator delete(void *mem)noexcept {
    free(mem);
}
void* NewAndDelete::operator new(size_t size, nothrow_t& no)noexcept {//不抛出异常,返回空指针
    void *p;
    if (void *mem = malloc(size))
        return mem;
    else return p;
}
void NewAndDelete::operator delete(void *mem, nothrow_t& no)noexcept {
    free(mem);
}
#endif
posted @ 2018-12-22 19:26  zhizhiyu  阅读(751)  评论(0编辑  收藏  举报