一.new的基本用法
1.c++通过new关键字进行动态分配内存。
2.new开辟的空间存储在堆上,而我们定义的变量存储在栈上。
3.new分配的空间使用delete释放,new[] 使用 delete[]。
4.
int* pi = new int(5);//表示动态分配一个int ,初始化为 5
int* pa = new int[5];//表示动态分配一个数组,数组大小为5
二.new和malloc的区别
1.malloc与free是C++/C语言的标准库函数,new/delete是C++的运算符。它们都可用于申请动态内存和释放内存。
2.对于非内部数据类型的对象而言,光用maloc/free无法满足动态对象的要求。对象在创建的同时要自动执行构造函数,对象在消亡之前要自动执行析构函数。 由于malloc/free是库函数而不是运算符,不在编译器控制权限之内,不能够把执行构造函数和析构函数的任务强加于malloc/free。
3.new操作符内存分配成功时,返回的是对象类型的指针,类型严格与对象匹配,无须进行类型转换;malloc内存分配成功则是返回void * ,需要通过强制类型转换将void*指针转换成我们需要的类型。
4.new内存分配失败时,会抛出bac_alloc异常,它不会返回NULL;malloc分配内存失败时返回NULL。
5.使用new操作符申请内存分配时无须指定内存块的大小,编译器会根据类型信息自行计算;malloc则需要显式地指出所需内存的尺寸。
三.应用
//这看起来似乎是一个单一运算,它其实是由两个步骤完成。
//这里的new 相当于 new operator
int *pi = new int(5);
1.通过适当的new运算符函数实例,配置所需的内存:
int *pi = __new(sizeof(int));
2.将配置得来的对象设立初值:
*pi = 5;
更进一步地说,初始化操作应该在内存配置成功(经由new运算符)后才执行。
3.delete运算符情况类似。
delete pi;
如果pi的值为0,c++语言会要求delete运算符不要有操作。因此编译器必须为此调用构造一层保护膜:
if(pi != 0)
{
__delete(pi);
}
注意:pi并不会因此被自动清除为0;
4.new 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()只是分配了内存空间。
②通过placement new来调用构造函数
void* operator new (std::size_t size, void* ptr) noexcept;
placement new不需要抛出异常,因为它自身不分配内存。
ptr指针是已经分配好的,可能在栈上也可能在堆上。
placement new仅在一个已经分配好的内存指针上调用构造函数,placement new 知道如何用就可以了,是编译器编译时候做的事情,不需要我们控制。