一.C/C++内存分布图
作为C/C++方向的从业者,必须关注的四块空间:
- 栈(局部数据)
- 堆(动态申请数据)
- 数据段(全局数据和静态数据)
- 代码段(可执行代码和可读常量)
int globalVar = 1; static int staticGlobalVar = 1; void Test() { static int staticVar = 1; int localVar = 1; int num1[10] = { 1, 2, 3, 4 }; char char2[] = "abcd"; const char* pChar3 = "abcd"; int* ptr1 = (int*)malloc(sizeof(int) * 4); int* ptr2 = (int*)calloc(4, sizeof(int)); int* ptr3 = (int*)realloc(ptr2, sizeof(int) * 4); free(ptr1); free(ptr3); }
解析:
globalVar定义在所有的函数外,所以是全局变量,位于数据区
staticGlobalVar定义在函数体外[全局],且被static修饰[静态],所以是静态(全局)变量,位于数据区
staticVar定义在函数体外[局部],且被static修饰[静态],所以是静态(局部)变量,位于数据区
localVar定义在函数体内[局部],所以是局部变量,位于栈区
num1是整型数组名,定义在函数体内[局部],所以是局部变量,位于栈区
char2是字符数组名,定义在函数体内[局部],所以是局部变量,位于栈区
*char2是字符数组存放的内容,位于栈区
pChar3是一个指针,指向代码段中常量字符串“abcd”,定义在函数体内[局部],位于栈区
*pChar3是常量字符串“abcd”,位于代码段
ptr1指向动态申请的空间,定义在函数体内[局部],位于栈区
*ptr1是动态申请的空间里的内容,位于堆区
关于第7题和第9题区别:
二.new和delete内存管理
C 语言中的malloc是函数,C++中的new是关键字,操作符,都是在堆上动态申请的空间
下面我针对内置类型和自定义类型比较new,delete和malloc,free
1.对于内置类型
C 语言和C++默认都没有对各自动态申请的内存进行初始化
int main() { //C语言 int* p1 = (int*)malloc(40); free(p1); //C++,默认不初始化 int* ptr1 = new int; delete ptr1; //指定初始化 int* ptr2 = new int(100); //ptr2 = nullptr;如果后面不使用了,可以置空 delete ptr2; //动态申请数组 //不初始化 int* ptr3 = new int[10]; delete[] ptr3; //完全初始化 int* ptr4 = new int[10]{ 1,2,3,4,5,6,7,8,9,10 }; delete[] ptr4; //不完全初始化 int* ptr5 = new int[10]{ 1,2,3,4,5 }; delete[] ptr5; return 0; }
对于内置类型:
new/delete相比与malloc/free,只是用法上的区别
2.对于自定义类型(重点)
new/delete主要是针对自定义类型设计的,对于自定义类型,
new除了在堆上开辟空间,还会自动调用构造函数,完成对象的初始化
delete除了在堆上释放空间,还会自动调用析构函数,完成对象的资源清理
class A { public: A(int a = 10) :_a(a) { cout << "构造函数" << endl; } ~A() { cout << "析构函数" << endl; } private: int _a; }; int main() { A* ptr1 = new A; delete ptr1; cout << "____________________________________" << endl << endl; A* ptr2 = new A[4]; delete[] ptr2; return 0; }
案例:对于我们之前学过的单链表那块
C语言:
ListNode* BuyListNode(int val) { ListNode* newnode = (ListNode*)malloc(sizeof(ListNode)); newnode->_val = val; newnode->_next = nullptr; } int main() { ListNode* n1 = BuyListNode(1); ListNode* n2 = BuyListNode(2); ListNode* n3 = BuyListNode(3); n1->_next = n2; n2->_next = n3; return 0; }
C++:
struct ListNode { int _val; ListNode* _next; ListNode(int val = 0) :_val(val) ,_next(nullptr) {} }; int main() { //创建链表 ListNode* n1 = new ListNode(1); ListNode* n2 = new ListNode(2); ListNode* n3 = new ListNode(3); ListNode* n4 = new ListNode(4); ListNode* n5 = new ListNode(5); n1->_next = n2; n2->_next = n3; n3->_next = n4; n4->_next = n5; return 0; }