您的位置:首页 > 其它

new/delete/malloc/calloc/realloc/free

2010-06-15 23:35 316 查看
1) malloc/calloc/realloc/free
l malloc与calloc(个数,单个元素大小)的区别在于malloc不会初始化内存区,而calloc返回内存区地址时会先初始化内存区为0。
l realloc(指针,新大小)用户将一个内存区扩大
用它的好处在于当有连续的容量足够容纳新大小的内存时,不需要移动原先的数据到新内存区。
l malloc和free的缺点在于,其是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的性能都是一样的,因为每次系统内存使用状况可能不一样,导致搜索一块符合大小的内存所需的时间也是不一样的。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: