new/delete/malloc/calloc/realloc/free

1)          malloc/calloc/realloc/free

l       malloccalloc(个数,单个元素大小)的区别在于malloc不会初始化内存区,而calloc返回内存区地址时会先初始化内存区为0

l       realloc(指针,新大小)用户将一个内存区扩大

用它的好处在于当有连续的容量足够容纳新大小的内存时,不需要移动原先的数据到新内存区。

l      mallocfree的缺点在于,其是C标准函数,无法调用C++构造与析构函数

 

2)          new

l       优点

可调用构造函数,内置的内存长度计算、类型转换、异常抛出等。

l       new异常

当内存耗尽时,如再分配内存,就会调用默认的new-handler,而它抛出bad_alloc异常。这时,对象构造函数还没有被调用,也不会被调用了。

所以,如果不想抛出异常,就重定义new-handler

#include <new>

void Func()

{

//出错信息

//也可以在这里回收些内存,然后再次分配

}

 

set_new_hanlder(Func);

 

l       new重载

1 void* operator new(size_t size) throw(bad_alloc)

     { 分配内存,返回p} //需要防止里面调用new,递归调用,要用全局的::new

为什么返回void*而不是具体的对象,因为要通用,而且目前为止,编译器还没有为其调用构造函数,对象还没初始化呢。

2  void* operator new(size_t, const char* file, int 

        LineNumber);

事实上,参数可以任意多。

调用时:

char* p = new(__FILE__, __LINE__) char;

有时候可用于调试内存泄露。

 

为了简洁,可以用宏定义:

#define new new(__FILE__, __LINE__)

3)可选择类或全局重载,全局重载会影响其他对象的创建。

4)当重载了new时,也要注意重载new[],否则创建对象数组时,调用的还是默认的new[]行为。

void* operator new[] (size_t size)

{

return ::new char[size];

或者

return operator new(size);

}

 

注意:当创建数组时,编译器传入的size比实际上的多4个字节,这是用来存数组大小的,当释放时,系统需要知道释放多少。

 

l       new placement 重载

1)   可将对象构建在特定的内存地址上,例如,内存是从内存池来的,对象要保存在它那里。

void* pAddress = GetFromPool();

A* p = new (pAddress) A(10); //默认placement调用,只有一个参数。

2)   placement重载

void* operator new(size_t, void* address, 其他参数)

{

return address;

}

其实,它就是new的多参数重载的版本。

 

3)          delete

l       delete必须与new配套使用。

l       如果分配用malloc,而删除用delete,这个结果是未定义的。

l       如果分配用new,而删除时用free,这个结果可能是析构函数未被调用。

l       在用完一个内存区时,习惯性的将指针置为NULL,这是因为:释放NULL指针不会有问题,而重复释放同一内存区就可能会导致程序崩溃。

 

l       delete重载

1)   void operator delete(void* p){ ::delete [] p;}

为什么参数是void*呢,因为这时候已经调用了析构函数,只能返回内存区的地址。

2)   可选择类或全局重载,全局重载会影响其他对象的释放。

3 当重载了delete时,也要注意重载delete[],否则释放对象数组时,调用的还是默认的delete[]行为。

void operator delete[] (void* p)

{

return ::delete [] p;
}

 

l       delete void*与内存泄露

delete 一个void类型的指针时,其只会释放内存,不会调用析构函数,因为:它不知道void类型的对象的析构函数在哪里。但是,

                       int* p = new int[1000];

                       void* pv = p;

                       delete [] pv; //没问题,反正内置类型不用调析构函数

 

l       数组的释放

Object* p = new Object[100];

delete p; //所有内存释放了,但是剩下的析构函数没有被调用

正确的做法是:

delete [] p;

或者,delete [100] p; //这种做法效率稍微高一点,不用取内存大小。但是分配和释放都需指定大小,容易出错,一般不用。

 

4)          综合

l       性能

不能保证每次new/malloc的性能都是一样的,因为每次系统内存使用状况可能不一样,导致搜索一块符合大小的内存所需的时间也是不一样的。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值