动态内存分配
C++和C语言的内存分区一样。
text和data段都在可执行文件中,由系统从可执行文件中加载;而bss段不在可执行文件中,由系统初始化。
Stack: 栈区,存放局部变量,按内存地址由高到低方向生长,其最大大小由编译时确定,速度快,但自由性差,空间不大。
Heap: 堆区,由程序员自己自由申请的空间,按内存地址由低到高方向生长,其大小由系统内存/虚拟内存上限决定,速度较慢,但自由性大,可用空间大。
每个线程都会有自己的栈,但是堆空间是共用的。
BSS区(未初始化数据段):存放为初始化的全局变量和静态变量,只占用内存空间,不占用文件空间,不给该段的数据分配空间,仅仅是记录了数据所需空间的大小。
DATA(初始化的数据段)(RW):可读写数据,存放初始化的静态变量和全局变量,为数据分配空间,数据保存在目标文件中,const定义的全局变量存放在 rodata段。
常量区(rodata):存放字符串,const修饰的全局变量也储存在rodata区内,而const修饰的局部变量依然在栈上。
静态变量是地址向下增长,全局常量是地址向上增长。
- 调用函数,形成栈帧—函数返回,释放栈帧
- 临时变量在栈帧中,释放栈帧后临时变量就可被覆盖,也就是被释放的掉
- 函数的返回值是通过寄存器返回给调用方
- C有字符串但没有字符串类型
- 循环时尽量使得外侧少,内侧多,这样可以减少循环指令跳转
new和delete是C++定义的内存分配的操作符,C语言的动态内存分配函数malloc和free在C++中依然可以使用,new和delete解决了一些malloc和free无法解决的问题。
new int; //new一个对象
new int [10]; //new十个对象
new int(10); //new一个对象初始化成10
new int[10]{10,1,2,3}; //new十个对象 初始化为(10,1,2,3,0,0,0,0,0,0)
malloc和new区别:
- malloc只开辟空间不初始化 ----- new开辟空间调用构造函数
- malloc失败会返回空指针 ------ new失败了抛异常
- malloc申请空间时需要计算 ------ new不需要
- malloc的返回值为void*必须要强转 ------ new不需要因为后跟的是空间的类型
free和delete区别:
- free只释放自己的空间如自己创建指针指向的空间不会被释放 ------ delete会调用析构函数 + 释放空间
new的底层其实是调用了operator new + 构造函数,然后operator new会调用malloc,如果malloc失败operator new会直接抛出异常。
delete的底层是调用operator delete + 析构函数 ,然后operator delete调用free如果free失败operator delete会直接抛出异常。
可以在汇编代码看到确实new调用了operator new。
如果遇到一个已经开辟好的空间,但是没有初始化,现在我们想要初始化,就要使用到replacement - new 重定位new 对这片空间显示调用构造函数。
int main()
{
Date* a = (Date*)malloc(sizeof(Date));
new (a)Date(1999, 1, 1);// 重定位new
cout << *a << endl;
free(a);
return 0;
}