【1++的C++初阶】之内存管理

作者主页:进击的1++
专栏链接:【1++的C++初阶】

文章目录

  • 一,C/C++的内存分布
  • 二,malloc,realloc,calloc的区别
  • 三,C++的内存管理- -new和delete
    • 初识new和delete
    • new和delete操作自定义类型
    • 深度剖析new与delete
    • 定位new
  • 四,new/delete与malloc/free的区别

一,C/C++的内存分布

【1++的C++初阶】之内存管理_第1张图片
如上图所示,C/C++程序在运行时占用的内存主要是这几部分

 1.  栈:函数栈帧是建立在栈中的,所以在栈中会存储一些非静态局部变量,函数参数,返回值等。
 2. 堆:我们动态申请的内存就在堆中。
 3. 内存映射段:后面的文章会涉及,暂时不是很了解。
 4. 数据段:全局变量,static修饰的变量,函数等。
 5. 代码段:const修饰的只读常量,可执行程序等。

二,malloc,realloc,calloc的区别

我们首先来说他们各自的作用与用法:

  1. malloc:malloc是C语言中用来动态申请内存的函数,它能够申请所输入参数大小的空间,单位为字节,并且malloc的类型为void*,因此,在使用时要进行强制类型转换。
  2. calloc:calloc和malloc的功能差不多,区别就是,在申请内存的同时,能够将内存初始化为0。
  3. realloc:reallocation主要进行扩容,其有两种扩容方式,一是,在原来申请内存的后面扩容,二是,由于其后面的内存不够,另找一块地方,将原来申请内存中的内容拷贝到新的申请的内存中。
  4. 它们申请失败都会返回NULL,因此要加断言或判断语句来进行判断是否申请成功。

三,C++的内存管理- -new和delete

初识new和delete

我们来看以下代码:

void Test()
{
	int* ptr1 = new int;//申请一个int类型的空间
	int* ptr2 = new int[3]{1,2,3};//申请三个int类型的空间,并将其分别初始化为1,2,3
	int* ptr3 = new int(10);//申请一个int类型的空间,并将其初始化为10
	
}
int main()
{
	Test();
	return 0;
}

其运行结果如下图:
【1++的C++初阶】之内存管理_第2张图片
以上就是new的几种用法,要注意的是,在第二种用法中,对开辟的空间要全部初始化,不能初始化部分。

再来看下面的代码:

void Test()
{
	int* ptr1 = new int;
	int* ptr2 = new int[3]{1,2,3};
	int* ptr3 = new int(10);
	delete ptr1;
	//delete[] ptr2;
	delete ptr2;
	delete ptr3;
}
int main()
{
	Test();
	return 0;
}

运行结果如下:
【1++的C++初阶】之内存管理_第3张图片
通过上述结果,我们发现new 要与delete搭配,当要释放申请了多个对象的连续空间时,就必须用delete [] xxx来进行释放。
也就是new [] 要与delete [] 搭配。

new和delete操作自定义类型

我们来看下面这段代码:

class Date
{
public:
	Date(int year = 2023, int month = 5, int day = 3)
		:_year(year)
		, _month(month)
		, _day(day)

	{
		cout << "Date()" << endl;
	}

	~Date()
	{
		cout << "~Date()" << endl;
	}
private:
	int _year;
	int _month;
	int _day;
};

void Test2()
{
	Date* p1 = (Date*)malloc(sizeof(Date));
	Date* p2 = new Date(2022,5,18);
	//Date* p3 = new Date[3];
	free(p1);
	delete p2;
	//delete[] p3;
}

运行结果如下:
【1++的C++初阶】之内存管理_第4张图片
将p2屏蔽后:
【1++的C++初阶】之内存管理_第5张图片
通过观察上述两张运行结果图,我们发现,使用new和delete编译器会自己调用其构造与析构函数,而使用malloc与free则不会。而对于内置类型,则几乎没区别。

深度剖析new与delete

我们将上述代码的汇编指令调出来,如下图:
【1++的C++初阶】之内存管理_第6张图片

在图中我们可以清楚的观察到,new先是调用了operator new然后调用了其构造函数。delete也是类似先调用其析构,再调用operator delete。那么什么是operator new和opertaor delete呢?

operator new 和operator delete是系统提供的全局函数与前面所学的类重载的函数是不同的;new在底层调用operator new全局函数来申请空间,delete在底层通过operator delete全局函数来释放空间。
operator new:该函数实际通过malloc来申请空间,当malloc申请空间成功时直接返回;申请空间失败,尝试执行空间不足应对措施,如果应对措施用户设置了,则继续申请,否则抛异常。malloc申请失败返回NULL,而new会抛异常。
operator delete: 该函数最终是通过free来释放空间的。

定位new

什么叫定位new?定位new就是已分配的原始内存空间中调用构造函数初始化一个对象。

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

定位new的简单使用如下代码:

void Test2()
{
	Date* p1 = (Date*)malloc(sizeof(Date));
	//Date* p2 = new Date(2022,5,18);
	//Date* p3 = new Date[3];
	new(p1)Date;//定位new显式调用构造函数
	 p1->~Date();//显式调用析构函数
	free(p1);
	//delete p2;
	//delete[] p3;
}

运行结果如下:
【1++的C++初阶】之内存管理_第7张图片

四,new/delete与malloc/free的区别

  1. new delete是操作符而malloc,free是函数。
  2. new可以就行初始化而malloc不可以。
  3. 对于自定义类型new,delete会调用构造与析构函数,而malloc,free不会。
  4. new申请空间失败后会抛异常而malloc会返回NULL.
  5. new相较于malloc用起来更加方便。

你可能感兴趣的:(1++的C++初阶,c++,c语言)