1.申请的内存所在位置
*存储区(free store)是C++基于new操作符的一个抽象概念,凡是new进行内存申请,该内存为*存储区。堆是操作系统中的术语,是操作系统所维护的一块特殊内存,用于程序的内存动态分配,malloc函数从堆上动态分配内存,free释放已分配的对应内存。
根据operator new的实现细节,free store不仅可以是堆,还可以是静态存储区。甚至可不为对象分配内存。
new (place_address) type。 place_address为指针代表一块内存地址,此时new调用特殊operator new即:
oid * operator new (size_t,void *) //不允许重定义这个版本的operator new
其只简单返回指针实参,new负责再指定地址进行对象初始化工作。
2.返回类型安全性
new分配内存成功时,返回对象类型的指针,类型严格与对象匹配,无需转换,类型安全(等价内存安全,不会试图访问没授权的内存区域)的操作符。
malloc则返回void *,需要通过强制类型转换将void *指针变成我们需要的类型。
3.内存分配失败时的返回值
new会抛出bac_alloc异常,不返回NULL(malloc返回);习惯在malloc后判断是否成功
int *a = (int *)malloc ( sizeof (int ));
if(NULL == a)
{
...
}
else
{
...
}
4.是否需要制定内存大小
new无须执行,编译器根据类型自行计算,malloc需要显式指出内存尺寸。
class A{...}
A * ptr = new A;
A * ptr = (A *)malloc(sizeof(A)); //需要显式指定所需内存大小sizeof(A);
5.是否调用构造函数/析构函数
new的三步:1、调用operator new函数(对数组是operator new[])分配一块足够大、原始未命名的内存空间来存储对象。2、编译器运行相应构造函数以构造对象,并为其传入初值。3、构造完后返回指定对象的指针。
delete的两步:1、调用对象的析构函数。2、编译器调用operator delete(数组operator delete[])函数内存空间。
malloc的反例:
class A
{
public:
A() :a(), b(1.11){}
private:
int a;
double b;
};
int main()
{
A * ptr = (A*)malloc(sizeof(A));
return ;
}
A的默认构造函数没有被调用,a,b没有被初始化。malloc/free对标准库中凡是需要构造的类型通通不合适!!!
6.对数组的处理
new会分别调用构造函数初始化每一个数组元素,释放对象时为每个对象调用析构函数。
malloc只给你一块内存地址就完事。
7.new与malloc是否相互调用
operator new/operator delete可以基于malloc实现,但反之不行。
void * operator new (sieze_t size)
{
if(void * mem = malloc(size)
return mem;
else
throw bad_alloc();
}
void operator delete(void *mem) noexcept
{
free(mem);
}
8.是否可以被重载
new可以。8个重载版本
//这些版本可能抛出异常
void * operator new(size_t);
void * operator new[](size_t);
void * operator delete (void * )noexcept;
void * operator delete[](void *)noexcept;
//这些版本承诺不抛出异常
void * operator new(size_t ,nothrow_t&) noexcept;
void * operator new[](size_t, nothrow_t& );
void * operator delete (void *,nothrow_t& )noexcept;
void * operator delete[](void *,nothrow_t& )noexcept;
9.直观重新分配内存
malloc分配后若内存不足使用realloc重新分配。realloc先判断当前指针所指的内存是否有足够的连续空间,有则原地扩大返回原本指针,不够新指定空间,拷贝源数据,释放源内存区域。
new没有。
10.客户处理内存分配不足
在operator new抛出异常前会先调new-bandler用户指定的错误处理函数。
namespace std
{
typedef void (*new_handler)();
}
指向了一个没有参数没有返回值的函数(错误处理函数),需要调用set_new_handler,这是一个声明与的标准库函数:
namespace std
{
new_handler set_new_handler(new_handler p ) throw();
}
set_new_handler的参数为new_handler指针,指向了operator new 无法分配足够内存时该调用的函数。其返回值也是个指针,指向set_new_handler被调用前正在执行(但马上就要发生替换)的那个new_handler函数。