C++学习笔记|C++内存管理笔记

C/C++内存分布 C/C++内存区域划分
C++学习笔记|C++内存管理笔记
文章图片

数据段的大小是根据VS2013开的全局数组测出来的,可能不是很准
各区域功能
  • 内核:操作系统使用的空间,用户不能读写
  • 栈:局部变量,局部数组等都在栈,栈向下生长,即栈往低地址生长
const修饰的变量得分情况,还得分c和c++
参考这个大佬的博客const修饰的变量的存储位置
  • 内存映射段:与系统有关,待了解
  • 数据段(静态区):存储全局数据和静态数据
  • 代码段(常量区):可执行代码(二进制指令)和只读常量
const修饰的是变量,所以不叫只读常量
随笔记录:0x7fffffff相当于INT_MAX的一半,
例子
//变量在内存里的分布demo #include #include using namespace std; //variable的意思是变量,var是variable的简称 int global_var; //数据段 static int static_global_var; //数据段(静态区) int main() { static int static_var; //数据段 int local_var; //栈 char a[10]="abcd"; //a在栈,数据也都在栈 *a; //*a在栈 char* b = "abcd"; //b在栈,数据在代码区(常量区) *b; //*b在代码区 int* ptr = (int*)malloc(10); //ptr在栈,开辟的空间在堆 *ptr; //堆 return 0; }

C++学习笔记|C++内存管理笔记
文章图片

C语言管理内存的方式
通过malloc、calloc、realloc、free
  • malloc在堆上开辟空间,但是不初始化
  • calloc==malloc+初始化,不仅会开空间还会初始化
  • realloc,扩容+拷贝数据,如果空间不够需要扩容时就用realloc
  • free释放空间,防止内存泄漏等问题
new和delete关键字
初识
//初始new delete int main() { //C int* ptr = (int*)malloc(sizeof(int)); free(ptr); //C++ int* pa = new int; delete pa; return 0; }

C++学习笔记|C++内存管理笔记
文章图片

概念
  • 什么是new?
new是C++的一个关键字,用于动态内存分配
malloc是一个库函数
  • 什么是delete?
delete是C++的一个关键字,用于释放动态开辟的内存
类比free
简单用法
//new、delete对于自定义类型调用构造、析构函数demo class A { public: A() { cout << "A()" << endl; } ~A() { cout << "~A()" << endl; } }; int main() { A* pa1 = (A*)malloc(sizeof(A)); free(pa1); cout << "malloc 和 free结束" << endl; cout << endl; A* pa2 = new A; delete pa2; cout << "new 和 delete结束" << endl; return 0; }

C++学习笔记|C++内存管理笔记
文章图片

从这也可以看出new和malloc的区别之一就是会不会调用构造函数,delete和free的区别之一就是不会调用析构函数
//new、delete内置类型数组和自定义类型数组 class A { public: A(){} A(int){}}; int main() { int* ptr = new int[10]; //开一个十个int大小的数组 delete[] ptr; int* ptr2 = new int(5); //开一个int大小的空间并且初始化为5 delete ptr2; A* pa = new A[10]; //开一个十个A类型大小的数组,调用十次构造函数 delete[] pa; A* pa2 = new A(5); //会调用构造函数A(int)进行构造 delete pa2; return 0; }

C++学习笔记|C++内存管理笔记
文章图片

汇编证明new的过程调用了构造函数
C++学习笔记|C++内存管理笔记
文章图片

原则上new和delete成对使用,如果new和free配对使用,可能造成程序崩溃.
  • 我们之前有了malloc和free来动态开辟空间,那为什么会出现new和delete?
答: new和malloc在处理内置(基本)类型上没有差别,都只是动态开辟一块空间,但是C++还有面向对象的特性,虽然malooc给对象开辟了空间但是不会调用构造函数和析构函数,所以就出现了更能满足需求的new和delete
###malloc、free和new、delete的区别
  1. malloc和free是函数,new和delete是操作符
  2. malloc不能对申请的空间初始化,new可以
  3. 针对自定义类型,delete可以调用析构函数完成对象内资源的清理,而free不行
  4. 用法上,malloc需要强转类型和计算类型大小,new不需要
  5. 对于错误的处理,malloc开辟失败返回空指针,而new直接抛出异常,需要对异常进行捕获
operator new和operator delete
  • operator new和operator delete是两个全局函数,而不是运算符重载
  • new底层调用operator new开辟空间
  • delete底层调用operator new释放空间
  • void* operator new(size_t)和void operator delete(void* )
#### operator new源码
这段源码在new.cpp中
void *__CRTDECL operator new(size_t size) _THROW1(_STD bad_alloc) {// try to allocate size bytes void *p; while ((p = malloc(size)) == 0) if (_callnewh(size) == 0) {// report no memory _THROW_NCEE(_XSTD bad_alloc, ); }return (p); }

由源码可以看出,如果返回的是空指针,则抛出异常
由源码可见operator new也不过是对malloc进行了封装
operator delete源码 这块没找到源码,找到的资料大概意思是:operator delete这个函数相当于对free进行了封装
【C++学习笔记|C++内存管理笔记】如果有大佬知道这个函数的源码位置,麻烦告诉我一下
随笔记录:operator delete释放空指针不报错
C++学习笔记|C++内存管理笔记
文章图片

operator new和operate delete专属类重载
//类内重载operator new和operate delete的demo #include using namespace std; class A { public: void* operator new(size_t n) { cout << "void* operator new(size_t n)" << endl; return nullptr; } void operator delete(void* p) { cout << "void operator delete(void* p)" << endl; } }; int main() { A* pa=new A; delete pa; return 0; }

C++学习笔记|C++内存管理笔记
文章图片

new和delete原理
new:调用operaotr new函数开辟空间,再在空间上调用构造函数
delete:调用析构函数释放空间内的资源,再调用operator delete函数释放对象对象的空间
new T[N]:调用operator new开辟空间,再调用N次构造函数
delete[]:先执行N次析构函数,再把开辟的对象空间释放掉
placement new
引论 我们说new与malloc的不同点之一是new会调用构造函数
回顾一下之前调用构造函数的情形:定义对象或者new一个对象时都会调用构造函数,且是自动调用的
如果我们要对malloc出来的空间手动调用构造函数应该怎么办?
此时就需要placement new,即定位new表达式
用法 placement new也叫定位new表达式
作用:在已分配的空间调用构造函数初始化对象
比如我们malloc后调用构造函数初始化对象
使用场景:内存池等
用法:new(指向对象的指针)类名(构造函数参数)
//定位new表达式的用法demo class A { public: A() { cout << "A()"<~A(); free(pa); return 0; }

C++学习笔记|C++内存管理笔记
文章图片

总结
  • 内存区域的划分,即每块区域可以放什么数据(语言层面)
  • new和delete和malloc和free的差别主要在于对自定义类型的处理上,这个处理包括开辟成功和开辟失败
  • new和delete的底层依赖于operator new()和operator delete()两个全局函数
  • operator new()和operator delete()两个全局函数可以理解为是对malloc和free进行了一层封装
  • 定位new表达式可以手动调用自定义类型的构造函数
  • C++更加推荐使用new和delete进行内存管理

    推荐阅读