一.new的基本用法
++通过new关键字进行动态分配内存。
开辟的空间存储在堆上,而我们定义的变量存储在栈上。
分配的空间使用delete释放,new[] 使用 delete[]。
4.
int* pi = new int(5);//表示动态分配一个int ,初始化为 5
int* pa = new int[5];//表示动态分配一个数组,数组大小为5
二.new和malloc的区别
与free是C++/C语言的标准库函数,new/delete是C++的运算符。它们都可用于申请动态内存和释放内存。
2.对于非内部数据类型的对象而言,光用maloc/free无法满足动态对象的要求。对象在创建的同时要自动执行构造函数,对象在消亡之前要自动执行析构函数。 由于malloc/free是库函数而不是运算符,不在编译器控制权限之内,不能够把执行构造函数和析构函数的任务强加于malloc/free。
操作符内存分配成功时,返回的是对象类型的指针,类型严格与对象匹配,无须进行类型转换;malloc内存分配成功则是返回void * ,需要通过强制类型转换将void*指针转换成我们需要的类型。
内存分配失败时,会抛出bac_alloc异常,它不会返回NULL;malloc分配内存失败时返回NULL。
5.使用new操作符申请内存分配时无须指定内存块的大小,编译器会根据类型信息自行计算;malloc则需要显式地指出所需内存的尺寸。
三.应用
operator
就是我们平常用的new
new operator实际上执行了以下几个步骤:
①调用operator new分配内存。
如果类本身未定义operator new,那么会调用全局的operator new。
// 全局 operator new
void * operator new(std::size_t size) throw(std::bad_alloc)
{
if (size == 0)
{
size = 1;
}
void* p;
while ((p = ::malloc(size)) == 0)
{ //采用 malloc 分配空间
std::new_handler nh = std::get_new_handler();
if (nh)
nh();
else
throw std::bad_alloc();
}
return p;
}
每个类可以重载operator new(),如果类自己定义了operator new(),则调用自己的定义的 operator new,而不是全局的。
通过定义可以发现operator new()只是分配了内存空间。
②.调用构造函数,将配置得来的对象设立初值。
new
函数operator new 通常声明如下:
void * operator new(size_t size);
其返回值类型是void * ,返回一个指针,指向一块原始的、未设初值的内存,函数中size_t参数表示需要分配多少内存。你可以重载operator new,加上额外的参数,但参数第一个类型必须是size_t。
例子:
void *rawMemory = operator new(sizeof(string))
这里的operator new将返回指针,指向一块足够容纳一个string对象的内存。和malloc一样,operator new唯一任务就是分配内存。
new
有时候你真的会想直接调用一个构造函数,偶尔会有一些分配好的原始内存,你需要在上面构建对象。有一个特殊版本的operator new,称为 placement new。
例子:
class Widget
{
public:
Widget(int widgetSize);
...
};
Widget *constructWidgetInBuffer(void *buffer,int widgetSize)
{
return new (buffer) Widget(widgetSize);
}
此函数返回指针,指向一个Widget 对象,它被构造于传递此函数的一块内存缓冲区上。其中指定一个自变量(buffer)作为new operator "隐式调用 operator new"时所用。于是,被调用的operator new 除了接受 "一定得有的size_t自变量" 之外,还接受了一个 void* 参数,指向一块内存,准备用来接受构造好的对象。这样的operator new 称为 placement new,看起来像这样:
void *operator new(size_t,void *location)
{
return location;
}
前面已经说了 operator new的目的是为对象找到一块内存,然后返回一个指针指向它。在placement new的情况下,调用者已经知道指向内存的指针了,placement new唯一需要做的就是将它获得的指针再返回。想要使用placement new 必须#include<new>
4.总结
1.如果你希望将对象产生于堆上,请使用new operator。
2.如果你只打算分配内存,请使用operator new,就不会调用构造函数。
3.如果你打算在堆对象产生时自己决定内存分配方式,请自己重载operator new。
4.如果你打算在已分配的内存中构造对象,请使用placement new。