C/C++内存管理核心解析:分布、管理方式与定位new应用


💗博主介绍:计算机专业的一枚大学生 来自重庆 @燃于AC之乐✌专注于C++技术栈,算法,竞赛领域,技术学习和项目实战✌💗

💗根据博主的学习进度更新(可能不及时)

💗后续更新主要内容:C语言,数据结构,C++、linux(系统编程和网络编程)、MySQL、Redis、QT、Python、Git、爬虫、数据可视化、小程序、AI大模型接入,C++实战项目与学习分享。

👇🏻 精彩专栏 推荐订阅👇🏻

点击进入🌌作者专栏🌌:
算法画解
C++

🌟算法相关题目点击即可进入实操🌟

感兴趣的可以先收藏起来,请多多支持,还有大家有相关问题都可以给我留言咨询,希望希望共同交流心得,一起进步,你我陪伴,学习路上不孤单!

文章目录

C/C++内存管理

内存分布

基础问题样例分析

cpp 复制代码
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";
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 //解引用,堆

说明

1.栈,--堆栈,非静态局部变量/函数参数/返回值等,向下增长;

2.对,程序运行时动态内存分配,可以向上增长;

3.数据段,存储全局数据和静态数据;

4.代码段,可执行的代码/只读常量;

5.内存映射段:高效的I/O,用于装载一个共享的动态内存库,用户可使用系统接口

创建共享共享内存,做进程间通信。

C++内存管理方式;

通过new和delete操作符进行动态内存管理。注意:申请和释放单个元素的空间,使用new和delete操作符,申请和释放连续的空间,使用new[]和delete[],注意:匹配起来使用。

重点:

内置类型

如果申请的是内置类型的空间,new和malloc,delete和free基本类似,不同的地方是:

new/delete申请和释放的是单个元素的空间,new[]和delete[]申请的是连续空间,而且new在申请空间失败时会抛异常,malloc会返回NULL。

自定义类型

new的原理

  1. 调用operator new函数申请空间;

  2. 在申请的空间上执行构造函数,完成对象的构造。

delete的原理

  1. 在空间上执行析构函数,完成对象中资源的清理工作;

  2. 调用operator delete函数释放对象的空间。

new T[N]的原理

  1. 调用operator new[]函数,在operator new[]中实际调用operator new函数完成N个对象空间的申请;

  2. 在申请的空间上执行N次构造函数。

delete[]的原理

  1. 在释放的对象空间上执行N次析构函数,完成N个对象中资源的清理

    2.调用operator delete[]释放空间,实际在operator delete[]中调用operator delete来释放空间。

注意:new和delete一定要搭配使用,否则可能会有内存泄漏等各种问题。

注意问题:

cpp 复制代码
#include<iostream>
using namespace std;

class A
{
public:
	A(int a1 = 0, int a2 = 0)
		:_a1(a1)
		, _a2(a2)
	{
		cout << "A(int a1 = 0, int a2 = 0)" << endl;
	}

	A(const A& aa)
		:_a1(aa._a1)
	{
		cout << "A(const A& aa)" << endl;
	}

	A& operator=(const A& aa)
	{
		cout << "A& operator=(const A& aa)" << endl;
		if (this != &aa)
		{
			_a1 = aa._a1;
		}
		return *this;
	}

	~A()
	{
		//delete _ptr;
		cout << "~A()" << endl;
	}

	void Print()
	{
		cout << "A::Print->" << _a1 << endl;
	}

	A& operator++()
	{
		_a1 += 100;

		return *this;
	}
private:
	int _a1 = 1;
	int _a2 = 1;
};

class B
{
public:
	/*~B()
	{
		cout << "~B()" << endl;
	}*/
private:
	int _b1 = 2;
	int _b2 = 2;
};

int main()
{
     //内置类型
	//int* p1 = new int[10]; // -> malloc
	//delete p1;             // -> free
	//free(p1); //可以
	//但是有些情况,析构函数如果有指针释放,可能会有内存泄漏的风险

	//自定义类型
	B* p2 = new B[10]; 
	delete p2;//没有析构函数不会崩溃,编译器优化,有就会崩溃
	 
        //原本是会在原有基础(80Byte)多申请4Byte,用于存大小,给析构函数,delete是从头开始释放内存
	//没有析构函数,就不会有前面

	//A* p3 = new A[10]; 
	//delete[] p3;//程序会崩溃

	return 0;
}

定位new

表达式(placement-new)

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

使用格式:

new (place_address) type 或者new (place_address) type(initializer-list)

place_address必须是一个指针,initializer-list是类型的初始化列表

使用场景:

定位new表达式在实际中一般是配合内存池使用。因为内存池分配出的内存没有初始化,所以如

果是自定义类型的对象,需要使用new的定义表达式进行显示调构造函数进行初始化。

在内存池申请空间,而不是一直在堆(内存)上频繁申请,注意效率更高。

加油!志同道合的人会看到同一片风景。

看到这里请点个赞关注 ,如果觉得有用就收藏一下吧。后续还会持续更新的。 创作不易,还请多多支持!

相关推荐
写代码的【黑咖啡】2 小时前
Python中的JSON处理(标准库)
开发语言·python·json
xiaoye-duck2 小时前
C++ 内存管理:自定义类型 new/delete 调用构造 / 析构深度解析
c++
Elias不吃糖10 小时前
Java Lambda 表达式
java·开发语言·学习
guygg8810 小时前
一级倒立摆MATLAB仿真程序
开发语言·matlab
暮色_年华10 小时前
随想 2:对比 linux内核侵入式链表和 STL 非侵入链表
linux·c++·链表
情缘晓梦.10 小时前
C语言指针进阶
java·开发语言·算法
世转神风-10 小时前
qt-字符串版本与数值版本互转
开发语言·qt
极客代码11 小时前
深入解析C语言中的函数指针:原理、规则与实践
c语言·开发语言·指针·状态机·函数·函数指针