C++的内存布局
在C++中内存被分为5个部分,分别是堆、栈、自由存储区、全局/静态存储区以及常量存储区。
自由存储区与堆的区别
堆是C语言和操作系统里的术语,它是由操作系统维护的一块特殊的内存,当C程序调用malloc函数进行动态内存分配时就是从堆上获取内存的,而调用free函数可以交还分配的内存。自由存储区是C++基于new和delete操作符的一个抽象概念,凡是通过new来申请的内存区域都可称为自由存储区。几乎所有的C++编译器默认都使用堆来实现自由存储区,即缺省的全局库函数operator new和operator delete也是按照malloc和free的方式来实现的,这时使用new操作符分配的对象,说它在堆或者自由存储区上都可以。不过operator new和operator delete是可以被重载的(自定义版本必须位于全局作用域或者类作用域中),可以使用其他内存来实现自由存储,比如静态存储区,这时自由存储区和堆就不是一个概念了。
new和malloc的区别,delete和free的区别
1)是否调用构造/析构函数
使用new表达式时会执行3步操作:
a)new表达式会调用一个名为operator new(或operator new[])的标准库函数。该函数分配以一块足够大的,原始的,未命名的以便存储特定类型的对象(或对象数组)。
b)编译器运行相应的构造函数以构造对象,并为其传入初始值。
c)对象构造完成以后返回一个指向该对象的指针。
使用delete表达式时会执行2步操作:
a)delete表达式会调用对象的析构函数。
b)编译器调用名为operator delete(或operator delete[])的标准库函数释放内存空间。
而malloc/free只是单纯地分配和释放内存空间,不会调用构造/析构函数。
2)返回类型的安全性
new操作符分配内存成功后,返回的是类对象类型的指针,不需要进行类型转换,所以new操作符是类型安全的。而malloc内存分配成功返回的是void*,需要进行强制类型转换换成需要的类型指针。
3)内存分配失败时的返回值
malloc内存分配失败时会返回NULL,而new不会,它会抛出bad_alloc异常。
4)是否需要指定内存大小
调用new操作符进行动态内存分配时无需指定内存大小,编译器会根据类型信息自行计算,而malloc需要显式地指定所需内存的大小。
5)是否可以被重载
operator new和operator delete可以被重载,标准库定义了operator new和operator delete的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&) noexcept;
void *operator delete(void *, nothrow_t&) noexcept;
void *operator delete[](void *, nothrow_t&) noexcept;
应用程序可以自定义上面函数版本中的任意一个,前提是自定义的版本必须在全局作用域或类作用域,当把它们定义为类成员函数时,它们是隐式静态的。malloc/free不允许重载。
参考自http://blog.jobbole.com/102002/
http://www.cnblogs.com/QG-whz/p/5060894.html