菜鸟笔记
提升您的技术认知

重载new和delete运算符-ag真人游戏

内存管理运算符 new、new[]、delete 和 delete[] 也可以进行重载,其重载形式既可以是类的成员函数,也可以是全局函数。一般情况下,内建的内存管理运算符就够用了,只有在需要自己管理内存时才会重载。

以成员函数的形式重载 new 运算符:

void * classname::operator new( size_t size ){
    //todo:
}

 

以全局函数的形式重载 new 运算符:

void * operator new( size_t size ){
    //todo:
}

 

两种重载形式的返回值相同,都是void *类型,并且都有一个参数,为size_t类型

在重载 new 或 new[] 时,无论是作为成员函数还是作为全局函数,它的第一个参数必须是 size_t 类型size_t 表示的是要分配空间的大小对于 new[] 的重载函数而言,size_t 则表示所需要分配的所有空间的总和。

重载的new必须有一个size_t参数。这个参数由编译器产生并传递给我们,它是要分配内存的对象的长度。必须返回一个指向等于这个长度(或者大于这个长度)的对象的指针。如果没有找到存储单元(在这种情况下,构造函数不被调用),则返回一个0。然后如果找不到存储单元,不能仅仅返回0,我们还应该调用new-handler或产生一个异常信息之类的事,告诉这里出现了问题。

我们首先需要明白的一点就是:operator new()的返回值是一个void*,而不是指向任何特定类型的指针。所做的是分配内存,而不是完成一个对象建立--直到构造函数调用了才完成对象的创建,它是编译器确保做的动作,不在我们的控制范围之内了,所以我们就没有必要考虑。

size_t 在头文件 中被定义为typedef unsigned int size_t;,也就是无符号整型。

当然,重载函数也可以有其他参数,但都必须有默认值,并且第一个参数的类型必须是 size_t。

同样的,delete 运算符也有两种重载形式。以类的成员函数的形式进行重载:

void classname::operator delete( void *ptr){
    //todo:
}

 

以全局函数的形式进行重载:

void operator delete( void *ptr){
    //todo:
}

 

两种重载形式的返回值都是 void 类型,并且都必须有一个 void 类型的指针作为参数,该指针指向需要释放的内存空间

当我们以类的成员函数的形式重载了new 和 delete 操作符,其使用方法如下:

c * c = new c; //分配内存空间
//todo:
delete c; //释放内存空间

 

如果类中没有定义 new 和 delete 的重载函数,那么会自动调用内建的 new 和 delete 运算符。

 

重载全局new和delete

#include 
#include
#include
#include
#include
#include
#include
#define inf 0x7fffffff
using namespace std;
void* operator new(size_t sz)
{
    printf("operator new: %d bytes\n",sz);
    void* m = malloc(sz);
    if (!m) puts("out of memory");
    return m;
}
void* operator new [](size_t sz)
{
    printf("operator new: %d bytes\n",sz);
    void* m = malloc(sz);
    if (!m) puts("out of memory");
    return m;
}
void operator delete(void* m)
{
    puts("operator delete");
    free(m);
}
void operator delete[](void* m)
{
    puts("operator delete");
    free(m);
}
class s
{
public:
    s() {puts("s::s()"); }
    ~s() {puts("s::~s()"); }
private:
    int an[1000];
};
void func()
{
    puts("creating & destroying an int");
    int* q = new int(23);
    delete q;
    puts("creating & destroying an int[]");
    int* p = new int[10]();
    delete []p;
    puts("creating & destroying an s");
    s* s = new s;
    delete s;
    puts("creating & destroying s[3]");
    s* sa = new s[3];
    delete []sa;
}
int main(int argc, char *argv[])
{
    qcoreapplication a(argc, argv);
    func();
    return a.exec();
}

 

输出:

creating & destroying an int
operator new: 4 bytes
operator delete
creating & destroying an int[]
operator new: 40 bytes
operator delete
creating & destroying an s
operator new: 4000 bytes
s::s()
s::~s()
operator delete
creating & destroying s[3]
operator new: 12004 bytes
s::s()
s::s()
s::s()
s::~s()
s::~s()
s::~s()
operator delete

 

对于一个类重载new和delete

为一个类重载new和delete的时候,尽管不必显式的使用static,但是实际上仍是在创建static成员函数。它的语法也和重载任何其它运算符一样。当编译器看到使用new创建自己定义的类的对象时,它选择成员版本的operator new()而不是全局版本的new()。但是全局版本的new和delete仍为所有其他类型对象使用(除非它们也有自己的new和delete)。这个和全局变量、局部变量的意思是一样的。

 

#include
#include
#include
#include
using namespace std;
ofstream out("framis.out");
class framis
{
public:
    enum{psize = 100 };
    framis() {out<< "framis()" <    cout << sizeof(framis) << endl;
    framis* f[framis::psize];
    try {
        for (int i=0; inew 的时候先跑进 new 重载函数中,再调用构造函数
        }
        new framis;
    } catch(bad_alloc) {
        cerr<< "out of memory!" <delete 的时候先调用析构函数,再跑进delete重载函数中
    for (int j=0; j

 


10 // sizeof framis
using block 0 ... framis()
using block 1 ... framis()
using block 2 ... framis()
using block 3 ... framis()
using block 4 ... framis()
using block 5 ... framis()
using block 6 ... framis()
using block 7 ... framis()
using block 8 ... framis()
using block 9 ... framis()
using block 10 ... framis()
using block 11 ... framis()
using block 12 ... framis()
using block 13 ... framis()
using block 14 ... framis()
using block 15 ... framis()
using block 16 ... framis()
using block 17 ... framis()
using block 18 ... framis()
using block 19 ... framis()
using block 20 ... framis()
using block 21 ... framis()
using block 22 ... framis()
using block 23 ... framis()
using block 24 ... framis()
using block 25 ... framis()
using block 26 ... framis()
using block 27 ... framis()
using block 28 ... framis()
using block 29 ... framis()
using block 30 ... framis()
using block 31 ... framis()
using block 32 ... framis()
using block 33 ... framis()
using block 34 ... framis()
using block 35 ... framis()
using block 36 ... framis()
using block 37 ... framis()
using block 38 ... framis()
using block 39 ... framis()
using block 40 ... framis()
using block 41 ... framis()
using block 42 ... framis()
using block 43 ... framis()
using block 44 ... framis()
using block 45 ... framis()
using block 46 ... framis()
using block 47 ... framis()
using block 48 ... framis()
using block 49 ... framis()
using block 50 ... framis()
using block 51 ... framis()
using block 52 ... framis()
using block 53 ... framis()
using block 54 ... framis()
using block 55 ... framis()
using block 56 ... framis()
using block 57 ... framis()
using block 58 ... framis()
using block 59 ... framis()
using block 60 ... framis()
using block 61 ... framis()
using block 62 ... framis()
using block 63 ... framis()
using block 64 ... framis()
using block 65 ... framis()
using block 66 ... framis()
using block 67 ... framis()
using block 68 ... framis()
using block 69 ... framis()
using block 70 ... framis()
using block 71 ... framis()
using block 72 ... framis()
using block 73 ... framis()
using block 74 ... framis()
using block 75 ... framis()
using block 76 ... framis()
using block 77 ... framis()
using block 78 ... framis()
using block 79 ... framis()
using block 80 ... framis()
using block 81 ... framis()
using block 82 ... framis()
using block 83 ... framis()
using block 84 ... framis()
using block 85 ... framis()
using block 86 ... framis()
using block 87 ... framis()
using block 88 ... framis()
using block 89 ... framis()
using block 90 ... framis()
using block 91 ... framis()
using block 92 ... framis()
using block 93 ... framis()
using block 94 ... framis()
using block 95 ... framis()
using block 96 ... framis()
using block 97 ... framis()
using block 98 ... framis()
using block 99 ... framis()
out of memory
out of memory!
~framis() ...
freeing block 10
using block 10 ... framis()
~framis() ...
freeing block 10
~framis() ...
freeing block 0
~framis() ...
freeing block 1
~framis() ...
freeing block 2
~framis() ...
freeing block 3
~framis() ...
freeing block 4
~framis() ...
freeing block 5
~framis() ...
freeing block 6
~framis() ...
freeing block 7
~framis() ...
freeing block 8
~framis() ...
freeing block 9
~framis() ...
freeing block 11
~framis() ...
freeing block 12
~framis() ...
freeing block 13
~framis() ...
freeing block 14
~framis() ...
freeing block 15
~framis() ...
freeing block 16
~framis() ...
freeing block 17
~framis() ...
freeing block 18
~framis() ...
freeing block 19
~framis() ...
freeing block 20
~framis() ...
freeing block 21
~framis() ...
freeing block 22
~framis() ...
freeing block 23
~framis() ...
freeing block 24
~framis() ...
freeing block 25
~framis() ...
freeing block 26
~framis() ...
freeing block 27
~framis() ...
freeing block 28
~framis() ...
freeing block 29
~framis() ...
freeing block 30
~framis() ...
freeing block 31
~framis() ...
freeing block 32
~framis() ...
freeing block 33
~framis() ...
freeing block 34
~framis() ...
freeing block 35
~framis() ...
freeing block 36
~framis() ...
freeing block 37
~framis() ...
freeing block 38
~framis() ...
freeing block 39
~framis() ...
freeing block 40
~framis() ...
freeing block 41
~framis() ...
freeing block 42
~framis() ...
freeing block 43
~framis() ...
freeing block 44
~framis() ...
freeing block 45
~framis() ...
freeing block 46
~framis() ...
freeing block 47
~framis() ...
freeing block 48
~framis() ...
freeing block 49
~framis() ...
freeing block 50
~framis() ...
freeing block 51
~framis() ...
freeing block 52
~framis() ...
freeing block 53
~framis() ...
freeing block 54
~framis() ...
freeing block 55
~framis() ...
freeing block 56
~framis() ...
freeing block 57
~framis() ...
freeing block 58
~framis() ...
freeing block 59
~framis() ...
freeing block 60
~framis() ...
freeing block 61
~framis() ...
freeing block 62
~framis() ...
freeing block 63
~framis() ...
freeing block 64
~framis() ...
freeing block 65
~framis() ...
freeing block 66
~framis() ...
freeing block 67
~framis() ...
freeing block 68
~framis() ...
freeing block 69
~framis() ...
freeing block 70
~framis() ...
freeing block 71
~framis() ...
freeing block 72
~framis() ...
freeing block 73
~framis() ...
freeing block 74
~framis() ...
freeing block 75
~framis() ...
freeing block 76
~framis() ...
freeing block 77
~framis() ...
freeing block 78
~framis() ...
freeing block 79
~framis() ...
freeing block 80
~framis() ...
freeing block 81
~framis() ...
freeing block 82
~framis() ...
freeing block 83
~framis() ...
freeing block 84
~framis() ...
freeing block 85
~framis() ...
freeing block 86
~framis() ...
freeing block 87
~framis() ...
freeing block 88
~framis() ...
freeing block 89
~framis() ...
freeing block 90
~framis() ...
freeing block 91
~framis() ...
freeing block 92
~framis() ...
freeing block 93
~framis() ...
freeing block 94
~framis() ...
freeing block 95
~framis() ...
freeing block 96
~framis() ...
freeing block 97
~framis() ...
freeing block 98
~framis() ...
freeing block 99

输出

 

为数组重载new和delete

上一段文字中我们讲到如果为一个类重载operator new()和operator delete(),那么无论何时创建这个类的一个对象都将调用这些运算符。但是如果要创建这个类的一个对象数组的时候,全局operator new()就会被立即调用,用来为这个数组分配足够的内存。对此,我们可以通过为这个类重载运算符的数组版本,即operator new[]和operator delete[],来控制对象数组的内存分配。

#include
#include
#include
using namespace std;
ofstream trace("arrayoperatornew.out");
class widget
{
public:
    widget() {trace<< "*" <

 


new widget
widget::new: 40 byte
*
delete widget
~
widget::delete
new widget[25]
widget::new[]: 1004 bytes
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
delete []widget
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
~
widget::delete[]

输出

 

 

c 空类的大小是1

 

网站地图