C++内存管理

目录

1.动态内存管理

1.1new和delete的使用

1.2对内置类型的操作

1.3对自定义类型的操作

2. operator new与operator delete函数

3. new和delete的实现原理

3.1 内置类型

3.2自定义类型

4.定位new表达式的使用

5.new、malloc和delete、free的区别

结语


1.动态内存管理

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

1.1new和delete的使用

对于new和delete操作符的使用,new和delete与C语言中的malloc和free的使用是相似的,new的功能对应malloc,是用于动态开辟一段空间,delete的功能对应free,是用于释放所开辟的空间。但要注意区分new和delete是操作符,malloc和free是函数

使用:对于不同的开辟元素个数,有着两种情况,使用时两组需要进行固定搭配使用,不要混搭使用,更不要配合C语言中的malloc和free函数使用,否则会出现意料之外的运行错误,导致程序崩掉。

1.new + 类型                           2.new +类型[对象个数]

delete + 待释放空间                delete[] + 待释放空间

 new和delete的使用对应两组不同的情况,一种是使用new动态开辟单个元素空间,此时需要搭配delete来释放空间,另一种是使用new配合 [ ] 进行的多个元素的动态内存开辟,此时需要配合delete[]来释放空间。此外,需要注意的是delete的使用对于动态开辟内存空间的释放与C语言是一致的,不能进行局部空间的释放,只能从头开始一次性全部释放

1.2对内置类型的操作

对与内置类型的操作,new和delete的作用分别与malloc和free的作用是相同的,new同样是只起到动态开辟内存的作用,delete也是只起到释放空间的作用。

new的使用在开辟单个或多个元素的情况下,也可以对开辟空间中的元素进行初始化,对于单个元素的初始化我们使用(),而对于多个元素的初始化使用{}

下面给出一些简单的例子:

单个元素内存空间的开辟:

对于单个元素的内存开辟,我们可以使用()进行元素初始化,未初始化的内存中存储的是随机值。

多个元素内存空间的开辟:

对于多个元素的内存开辟,我们使用{}进行初始化,与数组的元素的初始化如出一辙,对于不完全初始化,的剩余空间会默认置0,同于不进行初始化的,所存放的也是随机值。

1.3对自定义类型的操作

对于自定义类型的操作,new和delete的使用与C语言中的malloc和free的就有较大的差异了,C语言中的malloc和free在处理自定义类型一般是不太适用的

差异:

new在动态开辟自定义类类型的内存空间后,会自动调用该类类型的默认构造。

delete在释放空间之前,会先自动调用该类类型的析构函数

下面给一些简单的自定义类型的例子:
class A
{
private:
	int _a;
public:
	A(int a = 0)
		:_a(a)
	{
		cout << "A(int a = 0)" << endl;
	}
	~A()
	{
		cout << "~A()" << endl;
	}
};

我们通过new先后动态开辟的A类型的两段内存空间,最后运行结果会发现,p1所指向的空间在被开辟后,调用了类的构造函数,而在delete调p1所指向的空间后,显示器上也紧跟着一个析构函数的调用显示,同样对于指向,有3个元素空间的p2,在使用new和delete后都分别调用三次构造和析构函数。

2. operator newoperator delete函数

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

1.operator new:

operator new 函数实际上是一个对于malloc函数进行封装的函数,其进行的动态内存的申请最终也是通过malloc函数来实现的。malloc函数在申请空间成功后,会直接返回,而如果失败则会返回空,operator new 函数则对malloc函数申请空间失败情况进行了处理,在申请空间失败后向用户抛出异常。

2.operator delete:

对于operator delete函数,我们可以认为它与C语言中的free函数是相同的作用,没有什么区分,operator delete的出现主要是为了配对operator new的使用。

3.operator new[] 和operator delete[]

对于operator new[] 和operator delete[]函数,在实际上使用时,operator new[] 是对operator new函数的多次调用,完成对多个元素内存空间的开辟,同样,operator delete[]函数也是对operator delete的多次调用。

operator new 和 operator delete的使用,在用法上与 malloc和 free上也是相同的。

int main()
{
	int* p1 = (int *)operator new(sizeof(int));
	int* p2 = (int*)malloc(sizeof(int));
	operator delete (p1);
	free(p2);
	return 0;
}

3. newdelete的实现原理

对于不同类型的动态内存空间申请释放,new和delete会有不同的处理。

3.1 内置类型

对于内置类型的动态内存开辟释放:

new:

new / new[]操作符的本质是去调用函数operator new / new[],此外不做其他处理。而operator new 函数的本质又是一个对于malloc函数的封装,对malloc函数申请空间失败时会抛出异常的版本。

过程:new -> operator new -> malloc

delete:

delete / delete[]操作符的本质是去调用函数operator delete / delete[],此外不做其他理。而operator delete的本质是去调用free函数。

过程:delete -> operator delete -> free

所以我们可以认为在对内置类型操作时,new和delete与C语言中的malloc和free是具有不同用法但相同功能的区别

3.2自定义类型

对于自定义类型的空间申请释放,new和delete会做更多的处理。

new:

处理自定义类型时,new会额外调用该类的构造函数进行处理,在申请的空间上执行构造函数,完成对象的构造

过程:

1.new -> operator new -> malloc

2.调用构造函数,完成申请空间上对象的初始化。

delete:

处理自定义类型时,delete会先调用对象中的析构函数去销毁类对象成员的空间,然后再调用operator delete/delete[]。

过程:

1.调用析构函数销毁类对象成员内存空间。

2.delete -> operator delete -> free

4.定位new表达式的使用

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

对于已经预先开辟好对应类空间的情况,我们不能够直接去调用类中的构造函数,而要通过new表达式才能够调用构造函数初始化对象。定位new表达式在实际中一般是配合内存池使用,因为内存池分配出的内存没有初始化,所以如 果是自定义类型的对象,需要使用new的定义表达式进行显示调构造函数进行初始化。

使用格式:

带参的构造:new (place_address) 类名

不带参的构造:new (place_address)类名(initializer-list)

其中place_address必须是一个指针,initializer-list是类型的初始化列表
以下给出一些例子:
class A
{
private:
	int _a;
public:
	A(int a = 0)
		: _a(a)
	{
		cout << this << ":" << "A()" << endl;
	}
	~A()
	{
		cout << this <<":" << "~A()" << endl;
	}
};

我们使用operator new函数预先开辟好储存A对象的空间,如果我们要对类对象进行初始化,需要使用new表达式,选择调用带参与否的构造函数,不能使用指针加->的形式去调用构造函数,但我们可以通过指针加->的形式去调用类中的析构函数。

5.new、malloc和delete、free的区别

 相同点:

都是从堆区上申请空间,并且需手动释放。

不同点:

1.new和delete是操作符,malloc和free是函数。

2.new申请的内存空间可以初始化(内置、自定义类都可以),malloc不可以。

3.malloc申请空间时,需要手动计算要申请的空间大小并传递,而new只需在其后跟上空间的类型即可, 如果是多个对象,在[]中指定对象个数即可。
4.malloc申请空间失败时,返回的是空(NULL),因此使用时必须判空,new不需要,new会抛出异常,但是需要捕获异常。
5.对于自定义类型空间的申请释放,new会在申请空间后,调用构造函数初始化对象,malloc不会;delete在释放空间前会调用析构函数去清理类对象中的空间,free只会释放当前动态开辟的空间。

6.malloc的返回值为void*, 在使用时必须强转成对应类型,new不需要,new后跟的是空间的类型。

结语

这节对于C++中动态内存的知识介绍到这里就结束了,下期将继续带来C++相关的后续知识,感谢各位的观看,有错误或者需要改进的地方还请指出,如果有帮助的话,还请点个赞呀!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值