写代码常说的堆、栈
(一)堆
在写程序时用到的malloc、realloc、calloc、new操作都是在申请堆内存,每次使用完后记得释放掉(malloc-free)(new-delete),如果不释放掉操作系统也会释放,不过还是最好自己用完就释放。记住,接下来说的堆都是写程序我们所谓说的堆,这个堆只由操作系统来进行管理的,并不是堆数据结构,堆结构是抽象出来的一种结构,对于这个结构暂不讨论。
malloc和new的区别:
1、申请内存所在位置不同
new操作符从自由存储区上对对象动态内存分空间,而malloc函数从堆上动态分配内存。自由存储区是否是在堆上分配的内存,这取决于operator new的实现,由于自由存储区不仅可以选择堆,还可以是静态存储区,这看operator new在哪里为对象分配内存。
2、返回类型安全性
new操作符内存分配成功后返回的是对象类型的指针,类型严格与对象匹配,无需进行类型转换,故new是符合类型安全性的操作符,而malloc内存分配成功则是返回void*,需要通过强制类型转换成我们需要的类型。类型安全很大程度上可以等于内存安全。
3、内存分配失败时的返回值
new内存分配失败时会抛出bac_alloc异常,它不会返回NULL;
malloc分配内存失败时返回NULL。
4、是否需要指定内存大小
new不需要指定内存大小,编译器根据类型信息自行计算。
malloc则需要传入申请空间的大小,字节为单位。
5、是否调用构造函数/析构函数
使用new操作符时会经历三个步骤:
- 第一步:调用operator new分配一块足够大的空间,原始的,未命名的内存空间以便存储特定类型的对象
- 第二步:编译器运行相应的构造函数以构造对象,并为其传入初始值
- 第三步:对象构造完后返回一个指向该对象的指针
使用delete操作符来释放对象内存时会经历两个步骤:
- 第一步:调用对象的析构函数
- 第二步:编译器调用operator delete(operator ndelete[])函数释放内存空间
new/delete操作符会调用构造函数和析构函数来初始化对象和释放对象内存,做些清理工作。但是malloc函数不会这样做。
6、对数组的处理
new[]和delete[]专门为数组而设计。使用new[]分配内存必须使用delete[]来释放。
至于malloc函数,它不会知道你申请的那块空间时干什么用的,更不会知道那是一个数组,它只管分配一块你给定的内存大小。
7、new与malloc可不可以相互调用
operator new/ operator delete可以在重载的时候使用malloc函数来分配内存,但是不能使用malloc来调用new
8、是否可以被重载
new/delete可以被重载。
但是malloc不允许被重载。
9、能够直观的重新分配内存
malloc函数分配内存之后如果想重新扩充内存或者缩小内存可以使用realloc函数进行内存的重新分配。
而new不可以。
10、客户处理内存分配不足
在operator new抛出异常以反映一个未得到满足的需求之前,它会先调用一个用户指定的错误处理函数,这就是new_handler。new_handler是一个指针类型:
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函数。
对于malloc,客户并不能够去编程决定内存不足以分配时要干什么事,只能看着malloc返回NULL。
关于C语言的内存分区
1、代码区:存放经过编译生成的机器码指令
2、全局初始化区/静态区:存放初始化过的全局变量、静态变量(包含全局静态变量和局部静态变量)、常量(如字符串常量),只初始化一次,局部静态变量也只初始化一次,下次调用该函数,内部的局部静态变量不会被初始化。
3、未初始化数据区/BSS区:未初始化的全局变量,变量的值在运行时被改变。
4、栈区:存放局部变量、形式参数等一些寄存器值,由编译器来分配内存。
5、堆区:由用户动态分配内存,并且使用完后要记得释放,常用的动态内存申请的函数有malloc、realloc、calloc。包含C++中的new操作符。
(二)栈
写代码时说的栈只是用来存储局部变量和形式参数等等其它一些寄存器的值的一块存储区的简称。这里的栈和数据结构中说的栈结构是有区别的,这里的栈是操作系统里的内容,是一种一种内存管理机制,并不是数据结构里面学的栈结构。