C/C++内存分布
内存的分配方式有几种?
静态内存分配(Static Memory Allocation): 静态内存分配是在编译时确定内存大小和位置的分配方式。==全局变量、静态变量和常量都使用静态内存分配。==这些变量在程序的整个生命周期中都存在,直到程序结束。静态内存分配的优点是速度快,开销小;缺点是分配的内存大小在编译时就确定,不能在运行时改变。
栈内存分配(Stack Memory Allocation): ==栈内存分配是在函数调用期间为局部变量和函数参数分配内存的方式。==栈内存分配由编译器自动处理,无需程序员手动管理。栈内存分配速度快,但分配的内存大小受到栈大小的限制。当函数调用结束时,分配的内存会自动释放。
堆内存分配(Heap Memory Allocation): 堆内存分配是在程序运行期间动态分配和释放内存的方式。C++中,可以使用new
和delete
操作符(或new[]
和delete[]
操作符)在堆上分配和释放内存。堆内存分配允许在运行时分配可变大小的内存,但分配和释放的速度相对较慢,且需要程序员手动管理内存的生命周期。不正确地管理堆内存可能导致内存泄漏或悬挂指针等问题。
**注意:**静态内存分配具体又可以分为:数据段(静态区)和代码段(常量区)
#include<iostream>
using namespace std;
// 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);
}
C语言内存管理方式
malloc
和 free
仅分配和释放内存,而不对内存内容进行初始化。在 C++ 中,new
和 delete
操作符不仅负责内存分配和释放,还负责对象的构造和析构。
//C语言内存管理
void Test2()
{
int* p1 = (int*)malloc(sizeof(int));
free(p1);
// malloc/calloc/realloc的区别是什么?
int* p2 = (int*)calloc(4, sizeof(int));//calloc会开辟空间后进行初始化赋值0
int* p3 = (int*)realloc(p2, sizeof(int) * 10);//realloc是对开辟后的空间进行二次扩容
// 这里需要free(p2)吗?
// 1.不需要若p2和p3指向的是同一块内存空间则free一次空间即可 2.若realloc扩容的地址改变了那么编译器会自动拷贝p2中的内容到p3后自动freep2
free(p3);
}
C++内存管理方式
new
和 delete
是 C++ 语言中用于在堆上分配和释放内存的操作符,它们不仅负责内存管理,还负责对象的构造和析构。
//C++内存管理
void Test3()
{
// 动态申请一个int类型的空间
int* ptr4 = new int;
// 动态申请一个int类型的空间并初始化为10
int* ptr5 = new int(10);
// 动态申请10个int类型的空间
int* ptr6 = new int[3];
delete ptr4;
delete ptr5;
delete[] ptr6;
}
- 注意:申请和释放单个元素的空间,使用new和delete操作符,申请和释放连续的空间,使用new[]和delete[]
- 注意:匹配起来使用很重要!不匹配使用结果是不确定的:可能会存在报错,具体原因在于自定义类型下的析构函数的调用
- 注意:在申请自定义类型的空间时,new会调用构造函数,delete会调用析构函数,而malloc与free不会
new与delete的实现原理
内置类型 :
如果申请的是内置类型的空间,new和malloc,delete和free基本类似,不同的地方是:new/delete申请和释放的是单个元素的空间,new[]和delete[]申请的是连续空间,而且new在申请空间失败时会抛异常,malloc会返NULL
自定义类型 :
- new的原理
- 调用operator new函数申请空间
- 在申请的空间上执行构造函数,完成对象的构造
- delete的原理
- 在空间上执行析构函数,完成对象中资源的清理工作
- 调用operator delete函数释放对象的空间
- new T[N]的原理
- 调用operator new[]函数,在operator new[]中实际调用operator new函数完成N个对
象空间的申请 - 在申请的空间上执行N次构造函数
- delete[]的原理
- 在释放的对象空间上执行N次析构函数,完成N个对象中资源的清理
- 调用operator delete[]释放空间,实际在operator delete[]中调用operator delete来释
放空间