C++内存管理

本文深入探讨了C++中的内存分布,包括栈、堆、静态区和常量区的区别,并通过示例解析了不同类型的变量在内存中的位置。同时,详细阐述了new操作符与malloc的区别,以及new和delete的使用规范,强调了内存泄露的危害。此外,还介绍了operator new和operator delete的作用以及定位new表达式的用法。
摘要由CSDN通过智能技术生成

内存分布

在这里插入图片描述

例题

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";
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在哪里?____ staticGlobalVar在哪里?____
staticVar在哪里?____ localVar在哪里?____
num1 在哪里?____
char2在哪里?____ *char2在哪里?___
pChar3在哪里?____ *pChar3在哪里?____
ptr1在哪里?____ *ptr1在哪里?____

🌸globalVar:全局变量,在静态区
🌸staticGlobalVar:静态全局变量,也在静态区
🌸staticVar:静态局部变量,在静态区

💥localVar:局部变量,在栈
💥num1:数组,在栈

💥char2是一个数组,在栈上开5字节空间(包括\0了),把数据拷贝过去
💥char2,解引用的时候char2是首元素地址,char2解引用就是首元素,首元素是栈上开的空间,所以char2在栈上

💥pchar3是定义在栈上的局部变量,所以在栈上
🐶pchar3在栈上,但是它指向的空间在常量区,所以*pchar3在常量区

💥ptr1是局部变量,在栈上
🐹 *ptr1在堆

填空:
sizeof(num1)=40;因为初始化的时候指定了大小
sizeof(char2) = 5 因为包含了’\0’
; strlen(char2) = 4计算长度时遇到’\0’停止;
sizeof(pChar3) = 4,pchar3是指针,在32位平台占4个字节
_; strlen(pChar3) = 4;“abcd”在常量区,长度还是4
sizeof(ptr1) = 4因为是指针;

sizeof计算的是在空间上占多少字节,字符串包含’\0’
strlen计算字符串长度,遇到’\0’就停止

在这里插入图片描述

new操作符

malloc/ calloc /realloc 的区别

calloc he malloc 区别
calloc会初始化,相当于malloc+memset,按字节初始化,空间每个字节都初始化为0
realloc扩容,分为原地扩容和异地扩容

int main()
{
	//动态申请int和5个int 数组
	int* p1 = (int*)malloc(sizeof(int));//malloc会返回void*,所以要强制类型转换
	int* p2 = (int*)malloc(sizeof(int) * 5);
	//new的方法 new+类型
	int* p3 = new int;
	int* p4 = new int[5];//动态申请5个int空间
	//int* p5 = new int(5);//动态申请一个int空间,这块空间初始化为5

	free(p1);
	free(p2);
	delete p3;
	delete[] p4;//p4是数组要加[]
	p1 = nullptr;
	p2 = nullptr;
	p3 = nullptr;
	p4 = nullptr;
}

总结:
malloc/free 和 new/delete 对于内置类型没有本质区别,只有用法的区别
对于自定义类型,new不仅会申请空间,还会调用默认构造函数,让对象初始化;
delete会先调用指针类型析构函数,再释放空间给堆

一定要malloc free 和 new / delete ,new[] / delete[] 匹配使用
new失败了以后会要求抛异常,这样才符合面向对象语言的出错处理机制

简单拿个栈举例

class Stack
{
public:
	Stack(int capacity=4)//全缺省
		:_top(0)
		, _capacity(capacity)
	{
		_a = new int[capacity];
	}

	~Stack()
	{
		delete[] _a;
		_a = nullptr;
		_top = _capacity = 0;

	}
private:
	int* _a;
	int _top;
	int _capacity;
};

int main()
{
	Stack s1;
	Stack* ps2 = new Stack;//开空间+构造函数初始化

	delete ps2;            //析构函数(清理对象中的资源)+释放空间 
	return 0;
}

operator new与operator delete函数

operator new 和operator delete是系统提供的
全局函数


	Stack* pst1 =(Stack*) operator new(sizeof(Stack));

在这里插入图片描述

    Stack* p1 = new Stack[10];

	Stack* p1 = (Stack*)operator new[](sizeof(Stack) * 10);

在这里插入图片描述

operator newoperator delete 就是对mallocfree的封装
operator new中调用malloc申请内存,失败以后,改为抛异常处理错误,这样符合c++面向对象语言处理错误的方式

new和delete原理

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

定位new表达式


	Stack* sp1 = (Stack*)malloc(sizeof(Stack));
	//new(指针)Stack
	new(sp1)Stack;
	free(sp1)
	
	//等价于
	Stack* sp2 = new Stack();
	delete sp2;
	Stack* sp3 = (Stack*) operator new(sizeof(Stack));
	new(sp3)Stack();
	
	sp3->~Stack();//析构函数可以调用
	operator delete(sp3);

内存泄露危害

1.内存泄露 – 动态申请的内存,不使用了又没有主动释放,就存在内存泄露
2.内存泄漏的危害 ?
a.出现内存泄露的进程正常结束,进程结束时这些内存会还给系统,不会有什么伤害
b.出现内存泄露的进程非正常结束,如僵尸进程
c.需要长期运行的程序出现内存泄露,危害很大,系统会越来越慢,甚至宕机 --服务器程序

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值