new/delete 和 malloc/free 的区别
# new/delete 和 malloc/free 的区别与联系
+ malloc/free 则是库函数,而 new/delete 是运算符;
+ malloc 开辟空间需要手动计算大小并传入,new 是后接类型编辑器自己计算;
+ malloc 返回类型为 void*,使用时需要强制转换,new 返回类型就是后接的类型;
+ malloc 函数返回后需要判空使用,new 不需要,因为 new 失败后会抛出异常;
+ malloc 函数分配内存后,还可以使用 realloc 再次对分配的内存进行扩充或者缩小, new 分配好的内存不能这样被直观的改变;
+ new/delete 的底层实现使用了 malloc/free
+ malloc 申请内存位置是放在堆上,但是 new 申请内存的位置取决于 operator new 的细节实现,可能在自由存储区,也可以在堆上,也可以在栈上;
+ new/delete 在调用自定义对象时会自动调用对象的构造函数和析构函数,但是 malloc/free 不会去调用。
# new/delete 是如何实现的
+ new 的实现过程:首先调用名为 operator new 的标准库函数,分配足够大的原始为类型化的内存,已保存指定类型的一个对象;接下来运行该类型的一个构造函数,用指定初始化构造对象;最后返回指向新分配并构造后的对象的指针;
+ delete 的实现过程:对指针指向的对象运行适当的析构函数,然后调用名为 operator delete 的标准库函数释放该对象所用内存;
# delete 和 delete[] 的区别
+ delete 只会调用一次析构函数;
+ delete[] 会调用数组中每个元素的析构函数;
# C++ 有几种类型的 new
在 C++ 中,new 有三种经典的使用方法:plain new,nothrow new 和 palcement new
+ plain new:就是我们经常使用的 new,定义如下:
void *operator new(std::size_t) throw(std::bad_alloc); void opeartor delete(void *) throw();
plain new 在空间分配失败的时候,抛出异常 std::bac_alloc 而不是返回 NULL,因此可以通过判断返回值是否是 NULL 是徒劳的。
+ npthrow new:nothrow new 在分配失败的情况下是不抛出异常,而是返回 NULL,定义如下:
void* operator new(std::size_t, const std::nothrow_t&) throw(); void operator delete(void*) throw();
+ placement new:这种 new 允许在一块已经分配成功的内存上重新构造对象或对象数组。placement new 不用担心内存分配失败,因为它根本不会分配内存,它做的唯一一件事就是调用对象的构造函数。定义如下:
void * operator new(size_t, void*); void operator delete(void*, void*);
使用 placement new 需要注意两点:
- placement new 的主要用途是反复使用一块比较大的动态分配的内存来构造不同类型的对象或者他们的数组;
- placement new 构造起来的对象数组,要显示的调用他们的析构函数销毁(析构函数并不能释放对象的内存),千万不要使用 delete ,这是因为 placement new 构造起来的对象或数组大小并不是一定等于原来分配的内存大小,使用 delete 会造成内存泄漏或者之后释放内存时出现运行错误。