商道如狼道 发表于 8 小时前

内存管理(C++版)

C/C++内存分布

程序颠末编译生成可执行的二进制程序,我们可以把虚拟历程地址分为以下四个空间:栈,堆,常量区,静态区。这四个区里面存贮的也是不一样的内容。
各个区域所存储内容的阐明


[*]栈/堆栈:用于建立函数栈帧,主要存储一些临时变量,如(非静态局部变量/函数参数/返回值等等),栈空间很小,在Linux中大概是8M。栈是向下增长的。
[*]内存映射段:是高效的I/O映射方式,用于装载一个共享的动态内存库。用户可使用系统接口 创建共享共享内存,做历程间通信。
[*]堆:用于程序运行时动态内存分配,堆是可以上增长的。栈空间很大,在Linux中大概是以G为单元。
[*]静态区/数据段:存储全局数据和静态数据。
[*]常量区/代码段:可执行的代码/只读常量。
下面通过口试体案例进行讲解各部门地点的位置
   int globalVar = 1;
static int staticGlobalVar = 1;
void Test()
{
        static int staticVar = 1;
        int localVar = 1;

        int num1 = { 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);
}
1. 选择题:   选项: A.栈  B.堆  C.数据段(静态区)  D.代码段(常量区)  
globalVar在那里?__C__    
staticGlobalVar在那里?_C___  
staticVar在那里?_C___    
localVar在那里?_A___  
num1 在那里?___A_    
char2在那里?_A___    
*char2在那里?__A_  
pChar3在那里?__A__        
*pChar3在那里?__D__  
ptr1在那里?__A__          
*ptr1在那里?__B__
 解析:
nums1是一个数组,存放在栈区,char2也是一个数组,它是在常量区有一串字符串,字符串拷贝到char2数组中,pChar3是一个指针,指针存的是常量字符串首元素的地址,这里*pChar3就是在常量里面了,ptr1开辟的是指向堆区的空间,因此*ptr指向的是堆区。
https://i-blog.csdnimg.cn/direct/42597743d656449cb4c861fb8f2e97a8.png
 动态管理方式

C语言中malloc/calloc/realloc/frees用法

malloc:void * malloc (size_t size);


[*]申请一块巨细为 size 的内存空间,申请成功,返回指向这块空间起始位置的指针
[*]新分配的内存块没有初始化,保留不确定的值
[*]如果函数无法分配申请的内存块,会返回一个空指针(NULL),因此 malloc 函数的返回值一定要检查
[*]此函数只负责申请 size 巨细的内存空间,并不知道未来会存放什么类型的数据,因此函数的返回值是 void*
calloc:void* calloc (size_t num, size_t size);


[*]函数的功能是为 num 个巨细为 size 的元素开辟一块空间,而且把空间的每个字节初始化为 0 
realloc:void* realloc (void* ptr, size_t size);


[*]函数的出现让动态内存管理更加机动,可以大概合理的使用内存,对内存的巨细做机动的调整。realloc 函数就可以做到对动态开辟内存巨细的调整
C++中使用的有new后面只有跟着申请的类型,在初始化的时候new 类型后面要加上(初始化的值),在申请多个的环境就是new 类型后面要加上[],申请多个并进行初始化的时候在[]后面加上{}初始化{}不赋值就是默认值,因此构造函数一点要有一个默认值以便使用。delete删除时用delete+删除的变量名就行,删除多个时候就是delete 变量名+[]。
   void Test()
{  
        // 动态申请一个int类型的空间  
        int* ptr4 = new int;    

        // 动态申请一个int类型的空间并初始化为10  
        int* ptr5 = new int(10);  

         // 动态申请3个int类型的空间  
        int* ptr6 = new int;  
        
         // 动态申请3个int类型的空间 并进行初始化 
        int* ptr6 = new int{1,2,3};  
        delete ptr4;  
        delete ptr5;  

        delete[] ptr6;
}
 C++中new delete相对与malloc free的优点

C++中的new不仅具可以开辟空间,还会进行函数的构造,delete相对与free不仅可以释放空间还会调用析构函数。
C++中new delete的用法

class A
{
public:
A(int a = 1)
: _a(a)
{
cout << "A():" << this << endl;
}
~A()
{
cout << "~A():" << this << endl;
}
private:。
int _a;
};
int main()
{

A* p1 = (A*)malloc(sizeof(A));
A* p2 = new A(1);
free(p1);
delete p2;

int* p3 = (int*)malloc(sizeof(int));
int* p4 = new int;

free(p3);
delete p4;

A* p5 = (A*)malloc(sizeof(A)*10);
//前三个初始化1,2,3后面的就是默认值
A* p6 = new A{1,2,3};

free(p5);
delete[] p6;

return 0;
} new与delete的底层原理 

operator new与operator delete是库函数,不是函数的重载。operator new是对malloc的封装而operator delete是对free_dbg函数的封装(这里可以理解为是对free函数的封装)。new和delete关键字是对operator new与operator delete的调用。
下图是通过反汇编来更好的理解new的底层:
https://i-blog.csdnimg.cn/direct/39e0584b43d64762ac1ef892464490c7.png
new A的原理


[*]调用operator new[]函数,在operator new[]中现实调用operator new函数完成N个对象空间的申请
[*] 在申请的空间上执行N次构造函数
delete的原理


[*]在释放的对象空间上执行N次析构函数,完成N个对象中资源的清算 
[*]调用operator delete[]释放空间,现实在operator delete[]中调用operator delete来释 放空间
 

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页: [1]
查看完整版本: 内存管理(C++版)