您的位置:首页 > 编程语言 > C语言/C++

C++内存管理(一)

2019-07-05 07:31 1431 查看

C++的内存分布:

C/C++中内存区域的划分包括以下几个方面:

一.内核空间: 用户代码不能读写;

二.栈: 由高地址向低地址增长;栈(堆栈)是一种运算受限的线性表(push和pop操作);栈是操作系统在建立某个进程或线程时,为这个线程建立的存储区域,在编译时可以指定需要的stack的大小;(先进后出原则)
栈用来存放函数的参数值,局部变量的值等;

三.内存映射区: 内存映射段是高效的I/O映射方式,用于装载一个共享的动态内存库。用户可使用系统接口创建共享共 享内存,做进程间通信

四.堆: 由低地址向高地址增长;堆通常可以被看做是一棵树的数组对象,总是一个完全二叉树;堆是在程序运行时而不是程序编译时向操作系统发出请求分配给自己内存,申请某个大小的内存空间----即 动态内存分配;(先进先出原则)
(通过malloc/calloc/realloc,new/delete进行动态内存分配)

五.数据段: 用来存放程序中已初始化的全局变量的一块内存区域;数据段属于静态内存分配;数据段存放的是全局变量和静态变量;

六.代码段: 代码段就是存储程序文本的,所以有时候也叫做文本段,指令指针中的指令就是从这里取得;代码段主要存储代码和常量等;

原理图如下所示:

C++内存管理方式:

C语言的内存管理:

我们知道在C语言中管理内存的方式是通过 malloc/calloc/realloc和free来进行内存管理;

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);
free(p2);
free(p3);
}

关于malloc,calloc和realloc的区别:
三者的声明分别是:
void* malloc(size_t size);
void* calloc (size_t num,size_t size)
void* realloc(void * ptr,size_t size)
它们都在stdlib.h函数库内;

1.malloc和calloc的区别为1块与n块的区别:malloc调用的形式为(类型 * )malloc(size);在内存的动态存储区域中分配一块长度为size字节的连续区间,返回该区域的首地址;calloc调用形式为(类型 * )calloc(n,size);在内存的动态存储区域中分配n块长度为size字节的连续区域,返回首地址;
2.malloc 不能初始化所分配的内存空间,而calloc能;
3.使用malloc时(内存空间还没有被重新分配)能正常运行,但经过一段时间(内存空间已经重新分配)可能会出现问题 ;
4.函数calloc将分配的内存空间中的每一位初始化为0;
5.realloc不能保证重新分配的内存空间和原来的内存空间在同一内存地址,它返回的指针很有可能指向一个新地址,所以在代码中必须把realloc的值重新赋给p;
如:p=(char *)realloc(p,old_size+new_size);

C++ 内存管理方式:

在C++中管理内存更多的 使用new和delete操作符

1.new和delete操作内置类型:

void Test(){
//动态申请一个int类型的空间:
int* ptr4=new int;       //动态分配4个字节的空间(一个int);

//动态申请一个内置类型的空间,初始化为10;
int ptr5=new int(10);    //动态分配4个字节的空间(一个int),并初始化为10;

//动态申请3个int类型的空间;
int ptr6=new int[3];     //动态分配12个字节的空间(3个int);

delete ptr4;
delete ptr5;
delete[] ptr6;
}


注意:申请和释放单个元素的空间,使用new和delete操作符,申请和释放连续的空间,使用new[]和 delete[],即

new和delete动态管理对象; new[ ] 和 delete[ ] 动态管理对象组;

2.new和delete操作自定义类型:

class Test {
public:
Test()
: _data(0){
cout<<"Test():"<<this<<endl;
}

~Test(){
cout<<"~Test():"<<this<<endl;
}
private:
int _data;
};

void Test2() {
// 申请单个Test类型的对象
Test* p1 = new Test;
delete p1;

// 申请10个Test类型的对象
Test* p2 = new Test[10];
delete[] p2;
}

在申请自定义类型的空间时,new会调用构造函数,delete会调用析构函数,而malloc与free不会;

new和delete的实现原理:

内置类型:

如果申请的是内置类型的空间,new和malloc,delete和free基本类似;不同的地方是:new/delete申请和释放的是单个元素的空间,new[]和delete[]申请的是连续空间,而且new在申请空间失败时会抛异常, malloc会返回NULL。

自定义类型:

1.new的原理:

(1)调用operator new函数申请空间;
(2)在申请的空间上执行构造函数,完成对象的构造;

2.delete的原理:

(1)在空间上执行析构函数,完成对象的清理工作;
(2)调用operator delete函数释放对象空间;

3.new T
的原理:

(1)调用operator new[]函数,在operator new[]中实际调用operator new函数完成N个对象空间的申请 ;
(2)在申请的空间上执行N次构造函数;

4.delete[]的原理:

(1)在释放的对象空间上执行N次析构函数,完成N个对象中资源的清理;
(2)调用operator delete[]释放空间,实际在operator delete[]中调用operator delete来释放空间;

常见问题:

malloc/free和new/delete的区别和联系:

相同点:

都是在堆上开辟内存空间,并且需要用户手动释放;

不同点:

1.malloc和free是函数,new和free是操作符;
2.malloc申请的空间不会初始化,但new申请的空间会初始化;
3.malloc在申请空间时,要计算需要申请的空间大小并传递,new只需在后加空间类型;
4.malloc的返回值为void*, 在使用时必须强转,new不需要;
5.malloc申请空间失败时,返回的是NULL,因此使用时必须判空,new不需要,但是new需要捕获异常;
6. 申请自定义类型对象时,malloc/free只会开辟空间,不会调用构造函数与析构函数,而new在申请空间后会调用构造函数完成对象的初始化,delete在释放空间前会调用析构函数完成空间中资源的清理;

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: