C/C++内存管理

C/C++内存管理

C++兼容C语言C++的内存管理机制和C语言是一样的,但是C语言malloc函数已经无法满足C++面对对象过程中销毁的需求,于是C++提出了新的内存管理函数newdelete

1. C/C++内存分布

将内存分成不同的区域是为了更好的管理,上面说过C++兼容C,所以内存分布都是一样的:

五大分区:

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

内存中还存在内核空间,但普通用户代码无法读写

2. C++动态内存管理

内存管理是为了对内存进行分类,使操作系统对内存能有更让的管理,C++提出了newdelete操作符进行动态内存管理,下面我们来讲讲使用细节

2.1 new和delete操作内置类型

代码演示:

void Test()
{
	int* ptr1 = new int; //申请一个整型,只是开空间
	delete ptr1; //释放

	double* ptr2 = new double(6.66); //申请一个浮点型,并初始化为6.66
	delete ptr2; //释放

	int* ptr3 = new int[8]; //申请8个int类型的空间
	delete[] ptr3; //释放8次
}

2.2 new和delete操作自定义类型

代码演示:

class A
{
	A(int a = 12)
		:_a(a)
	{
		cout << "A()" << endl;
	}
	~A()
	{
		cout << "~A()" << endl;
	}
private:
	int _a;
};

int main()
{
	//new/delete 和 malloc/free最大区别是 new/delete对于【自定义类型】除了开空间还会调用构造函数和析构函数
	A* p1 = (A*)malloc(sizeof(A)); //开空间
	A* p2 = new A(12); //开空间并初始化
	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); //开10个A类对象空间
	A* p6 = new A[10]; //开10个A类对象空间
	free(p5);
	delete[] p6;

	return 0;
}

总结:

  1. new不需要像malloc那样进行空指针判断,也不需要进行类型转换
  2. delete需要配套使用,比如new int 使用 deletenew int 使用 delete[]
  3. newdelete都可以用于自定义类型,会分别调用自定义类型的构造函数析构函数
  4. new/deletemalloc/free最大区别是 new/delete对于【自定义类型】除了开空间还会调用构造函数析构函数
  5. malloc 对应freenew 对应 delete,一定要搭配使用,避免引发问题

3. operator new 和 operator delete函数

newdelete是用户进行动态内存申请和释放的操作符,operator newoperator delete是系统提供的全局函数,new在底层调用operator new全局函数来申请空间,delete在底层通过operator delete全局函数来释放空间

Visual studio 2019中operator new底层实现:

void* __CRTDECL operator new(size_t const size)
{
	for (;;)
	{
		if (void* const block = malloc(size))
		{
			return block;
		}

		if (_callnewh(size) == 0)
		{
			if (size == SIZE_MAX)
			{
				__scrt_throw_std_bad_array_new_length();
			}
			else
			{
				__scrt_throw_std_bad_alloc(); //抛出异常
			}
		}
		// The new handler was successful; try to allocate again...
	}
}

Visual studio 2019中operator delete底层实现:

void __CRTDECL operator delete(void* const block, size_t const) noexcept
{
	operator delete(block);
}

void __CRTDECL operator delete(void* const block) noexcept
{
#ifdef _DEBUG
	_free_dbg(block, _UNKNOWN_BLOCK);
#else
	free(block);
#endif
}

Visual studio 2019中operator new[]底层实现:

void* __CRTDECL operator new[](size_t const size)
{
	return operator new(size); //原理调用的size次operator new函数
}

Visual studio 2019中operator delete底层实现:

void __CRTDECL operator delete[](void* const block) noexcept
{
	operator delete(block);
}
void __CRTDECL operator delete[](void* const block, size_t const) noexcept
{
	operator delete[](block);
}

4. new 和 delete实现原理

4.1 内置类型

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

4.2 自定义类型

new的原理:

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

delete的原理:

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

new T[N]的原理:

  1. 调用operator new[]函数,在operator new[]中实际调用operator new函数完成N个对

象空间的申请

  1. 在申请空间上执行N次构造函数

delete[]的原理:

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

5. 定位new

定位newnew的新用法,是为了对已经开辟但没有初始化的空间进行初始化

5.1 基本语法

定位new表达式是:在已分配的原始内存空间中调用构造函数初始化一个对象

使用格式:new(指针)type或者new(指针)type(初始化列表)

代码使用:

class A
{
public:
	A(int a)
		:_a(a)
	{
		cout << "A()" << endl;
	}
	~A() {
		cout << "~A()" << endl;
	}

private:
	int _a;
};
int main()
{
	A* p = (A*)malloc(sizeof(A));
	if (p == nullptr) {
		perror("malloc is failed");
		exit(-1);
	}
	new(p)A(1); //定位new,对已经定义的对象初始化

	return 0;
}

5.2 使用场景

使用场景:一般配合内存池使。因为内存池分配出的内存没有初始化,所以如果定义自定义类型对象,需要使用new的定义表达式进行显示调用构造函数进行初始化


C/C++内存管理到这里就介绍结束了,本篇文章对你由帮助的话,期待大佬们的三连,你们的支持是我最大的动力!

文章有写的不足或是错误的地方,欢迎评论或私信指出,我会在第一时间改正

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

茉莉蜜茶v

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

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

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

打赏作者

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

抵扣说明:

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

余额充值