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";
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);
}
在栈上的有:localVar、num1、char2、pChar3、ptr1、*char2(char2是数组,在栈上开辟了空间,char2是char2解引用后
将代码段的常量拷贝到char2数组上,即拷贝到栈上,故char2在栈上)
在堆上的有:*ptr1(*ptr1指向动态开辟的空间)
在数据段上:globalVar、staticGlobalVar、staticVar
在代码段上:*pChar3(pChar3是指针,pChar3是解引用后,指针指向常量的地址,故pChar3在代码段)
sizeof(num1) = 40; sizeof(char2) = 5; //(还有’/0’)
sizeof(pChar3) = 4; sizeof(ptr1) = 4; //指针32位情况下为4个字节,64为情况下为8个字节
strlen(char2) = 4; strlen(pChar3) = 4; //strlen遇’/0’结束
说明:
(1)栈又叫堆栈,非静态局部变量/函数参数/返回值等等,栈是向下增长的
(2)内存映射段是高效的I/O映射方式,用于装载一个共享的动态内存库。用户可以使用系统接口创建共享内存,做进程间通信。
(3)堆用于程序运行时动态内存分配,堆是可以向上增长的
(4)数据段:存储全局数据和静态数据
(5)代码段:可执行的代码/只读常量
扩展
int main()
{
char p[] = "hello";
cout << strlen(p) << endl; //5
cout << sizeof(p) << endl; //6
char p[] = "hello0"; //字符0的ASCII码值与数字0的不同
cout << strlen(p) << endl; //6
cout << sizeof(p) << endl; //7
char p[] = "hello\0"; //'\'将'0'转义为0,'/0'是一个整体
cout << strlen(p) << endl; //5
cout << sizeof(p) << endl; //7
char p[] = "hello\\0";
cout << strlen(p) << endl; //7 //第一个'\'转义,将'\\0'分为'\\'和'0'
cout << sizeof(p) << endl; //8
char p[] = "hello\\\0"; //第一个'\'转义,将'\\\0'分为'\\'和'\0'
cout << strlen(p) << endl; //6
cout << sizeof(p) << endl; //8
return 0;
}
二、C语言中动态内存管理方式
malloc:开空间
calloc:开空间 + 初始化
realloc:扩容
void Test()
{
int* p1 = (int*)malloc(sizeof(int));
free(p1);
int* p2 = (int*)calloc(4, sizeof(int));
int* p3 = (int*)realloc(p2, sizeof(int)* 10);
//p2不需要被free,p2已被扩容
free(p3);
}
三、C++内存管理
通过new和delete操作符进行动态内存管理。
1、new/delete操作内置类型
void Test()
{
//动态申请一个int类型的空间
int* ptr1 = new int;
//动态申请一个int类型的空间并初始化为10
int* ptr2 = new int(10);
//动态申请5个int类型的空间
int* ptr3 = new int[5];
delete ptr1;
delete ptr2;
delete[] ptr3;
}
2、new和delete操作自定义类型
class A
{
public:
A()
:_data(0)
{
cout << "A():" << this << endl;
}
~A()
{
cout << "~A():" << this << endl;
}
private:
int _data;
};
void Test1()
{
//申请单个A类型的空间
A* p1 = (A*)malloc(sizeof(A));
free(p1);
//申请10个A类型的空间
A* p2 = (A*)malloc(sizeof(A) * 10);
free(p1);
}
void Test2()
{
//申请单个A类型的空间
A* p1 = new A;
delete p1;
//申请10个A类型的空间
A* p2 = new A[10];
delete[] p2;
}
注:在申请自定义类型的空间时,new会调用构造函数,delete会调用析构函数,而malloc和free不会
四、operator new与operator delete函数
new和delete是用户进行动态内存申请和释放的操作符,operator new和operator delete是系统提供的全局函数,new在底层调用operator new全局函数来申请空间,delete在底层调用operator delete全局函数来释放空间。operator new实际也是通过malloc来申请空间,operator delete最终通过free来释放空间。
五、new和delete是实现原理
1、内置类型
new和malloc,delete和free基本类似,不同的是:new在申请空间失败时会抛异常,malloc会返回NULL。
2、自定义类型
new的原理:
(1)调用operator new函数申请空间。
(2)在申请的空间上执行构造函数,完成对象的构造。
delete的原理:
(1)在空间上执行析构函数,完成对象中资源的清理工作。
(2)调用operator delete函数释放空间。
new T[N]的原理:
(1)调用operator new[]函数,在operator new[]中实际调用operator new函数完成N个对象空间的申请。
(2)在申请的空间上执行N次构造函数。
delete T[N]的原理:
(1)在空间上执行N次析构函数,完成N个对象中资源的清理工作。
(2)调用operator delete[]释放空间,实际在operator new[]中调用operator delete释放空间。