C/C++内存管理

 1.C/C++中内存分布

  • 栈又叫做栈堆,非静态局部变量/函数参数/返回值等等。栈是向下增长的
  • 内存映射段是高效的I/O映射方式,用于装载一个共享的动态内存库,用户可使用系统接口创建共享内存,做进程间通信
  • 堆用于程序运行时动态内存分配,堆可以向上增长
  • 数据段(静态区)存储全局数据和静态数据
  • 代码段放可执行代码/只读常量

238ca78e486544bb9e22384c198d5ed3.jpeg

//text.cpp
#include<iostream>
using namespace std;


int globalvar = 1;
//全局变量放在静态区
static int staticvar = 1;
//全局静态变量也放在静态区
void Text()
{
	static int staticvar = 1;
	//局部静态也放在静态区
	int localvar = 1;
	//局部变量,放在栈里
	int num[10] = { 1,2,3,4,5 };
	//数组放在栈内
	char char2[] = "abcd";
	//将" a b c d \0" 拷贝给数组char2, 数组放在栈
	*char2;
	//数组名代表整个数值,对其解引用得到首元素,数值仍在栈内
	const char* pchar3 = "abcd";
	//const修饰,pchar3指向的内容不可修改,局部变量仍然在栈上开辟空间
	*pchar3;
	//数组名代表整个数值,对其解引用得到首元素,而"a b c d \0"是临时变量,所以存放在常量区

	//变量的开辟在栈内
	int* ptr1 = (int*)malloc(sizeof(int) * 4);
	int* ptr2 = (int*)calloc(4,sizeof(int));
	int* ptr3 = (int*)realloc(ptr2, sizeof(int) * 4);

//动态开辟的内存在堆区,解引用得到首元素地址
	*ptr1;
	*ptr2;
	*ptr3;
	free(ptr1);
	free(ptr3);	
}


int main()
{


	return 0;
}

2.C语言中动态内存管理方式:malloc/calloc/realloc/free

http://t.csdnimg.cn/sruBN

3.C++内存管理方式

C语言内存管理方式在C++中可以继续使用,但有些地方就无能为力,而且使用起来比较麻烦,因此·C++又提出了自己的内存管理方式:通过new和delete操作符进行动态内存管理

	//text.cpp
#include<iostream>
using namespace std;



class A {
public:
	A(int a=0,int b=0)
{}
~A()
{}

};


int main()
{
	//动态申请一个int 类型的空间
	int* p1 = new int;
	//释放p1指向的空间
	delete p1;

	//动态申请10个int 类型的空间
	int* p2 = new int[10];
	//释放p2指向的空间
	delete[] p2;

	//动态申请+初始化
	int* p3 = new int(5);
	int* p4 = new int[10]{ 1,2,3,4,5 };

	delete p3;
	delete[] p4;
	//动态申请一个A类并默认构造初始化
	A* p5 = new A;
	//动态申请一个A类并带参构造初始化
	A* p6 = new A(1,0);
	A* p7 = new A(1);
	//动态申请一个A类数值并默认构造初始化
	A* p8 = new A[3]{ {},{},{} };
	//动态申请一个A类数值并带参构造初始化
	A* p9 = new A[3]{ {1,2},{3,4},{5,6} }; 
	A* p10 = new A[3]{ {1,2},{3,4},{} };
	A* p11 = new A[3]{ {1,2} };

	//先默认构造出三个对象,然后拷贝构造给动态开辟的数组
	A aa1(1, 2);
	A aa2(3, 4);
	A aa3(5, 6);
	A* p12 = new A[3]{ aa1,aa2,aa3 };
	A* p13 = new A[3]{ A(1,2),A(3,4),A(5,6) };
	return 0;
}

 new和delete会调用构造和析构

class A {
public:
	A(int a=0,int b=0)
{
		cout << "A(int a=0,int b=0)" << endl;
	}
~A()
{
	cout << "~A()" << endl;
}
int _a1 = 1;
int _a2 = 2;
};

int main()
{
	A* ptr1 = new A;
	delete ptr1;
	return 0;
}

 8cbda35eff6d43c59c9ad2deb32c78ad.png

注意:申请和释放单个元素的空间,使用new和delete操作符,申请和释放连续的空间用new[]和delete[]。一定要匹配起来使用,否则容易内存泄漏,如下

class A {
public:
	A(int a=0,int b=0)
{}
~A()
{}
int _a1 = 1;
int _a2 = 2;
};
class B {

private:
	int _b1 = 1;
	int _b2 = 2;

};
int main()
{//不报错
	int* p1 = new int[10];// ->malloc
	delete p1;            //->free

	B* p2 = new B[10];
	delete p2;

	//报错
	A* p3 = new A[10];
	delete p3;
	return 0;
}

自定义类型在创建时会额外开一个整形放在开头记录对象个数,而编译器看到B没有写析构函数而优化了所以没有开,这个整形开辟是方便delete[]释放的,B释放的ptr2的指向的空间,释放完全,而A还有一个整型大小没有释放,所以内存泄漏报错

978c176f3c3844318383c9858933567a.jpeg

4.operator new 与 operator delete函数

  • new和delete是用户进行动态内存申请和释放的操作符,operator new 和operator delete 是系统提供的全局函数,new在底层调用operator new全局函数来申请空间,delete在底层通过operator delete全局函数来释放空间
  • operator new 实际也通过malloc来申请空间的,如果malloc
  • 申请成功直接返回地址,否则执行用户提供的空间不足应对措施,如果用户提供该措施就继续申请,否则就抛异常。operator delete最终是通过free来释放空间的

5.new 和 delete的实现原理


内置类型

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

自定义类型

  • new的原理
  1. 调用operator new函数申请空间
  2. 在申请空间上执行构造函数,完成对象的构造
  • delete的原理
  1. 在空间上执行析构函数,完成对象中资源的清理工作
  2. 调用operator delete函数释放对象的空间
  • new T[N]的原理
  1. 调用operator new[]函数,在operator new[]中实际调用operator new函数完成对N个对象空间的申请
  2. 在申请的空间上执行N次构造函数
  • deleted[]的原理
  1. 在释放的对象空间上执行N此析构函数,完成对N个对象中资源的清理
  2. 调用operator delete[]释放空间,实际在operator delete[] 中调用operator delete来释放空间

     

评论 18
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

网恋露被录屏她闺蜜看了抢着和我处大象

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值