C++内存管理

本文介绍了C++中的动态内存管理,包括new运算符用于在堆上创建对象和数组,以及delete运算符用于释放内存。强调了new和delete的正确使用,如必须配对使用,以及new可以初始化对象而malloc不行等关键点。同时,提到了动态内存分配可能导致的内存泄漏问题,并给出了malloc/free与new/delete的区别。
摘要由CSDN通过智能技术生成


在这里插入图片描述

前言

  • 对于类型相同的的大量数据,我们可以用数组来存储。数组是一种静态内存分配方法,其长度是固定的,由数组定义语句确定,由编译系统予以分配。
    在程序的运行过程中,有时我们很难事先确定需要多少数组元素,只能按照预先估算的最大数量进行定义,这样会造成一大部分内存的浪费,而且一旦超过预先定义的最大个数,数组就会越界,造成程序异常。
    动态内存分配技术可以保证程序在运行过程中根据实际需要申请适量的内存,使用结束后还可以释放并返回给系统。C++通过new运算符和delete运算符实现动态内存分配。

如需查看C语言动态管理,请点击查看我往期博客。

new 运算

new运算的作用是按照指定的类型和大小动态地去分配内存,基本语法如下:
指针变量 = new 类型名 (初值列表);
其中:

  • 数据类型可以是内置的数据类型,也可以是用户自定义的复杂数据类型。
  • new 运算符在堆(内存)中创建一个由类型名指定类型的对象,如果创建成功,返回对象的地址,否则返回空指针nullptr
  • 初值列表给初被创建对象的初始值。
  • 由于返回的是地址,所以要用实现定义好的一个相同类型的指针变量去接收这个地址。

例①:

创建一个数据对象

	int* pi = new int(10);		//pi指向一个初始值为10的 int 型的对象
	
	//也可以使用分开定义,如下
	int* pj;
	pj = new int(10);

首先我们定义了一个整形指针pi,然后使用new运算符去申请内存空间来创建一个初始值为10的int型数据对象,最后返回创建好的数据对象的地址存入到pi当中。

创建多个数据对象----即数组

当然new运算符也可以像c语言当中的malloccalloc一样创建多个同类型的对象。new运算符创建动态数组时,需要给出数组的结构说明。其语法形式如下:
指针变量 = new 类型名 [下标表达式];
其中:

  • 下标表达式与数组初始化时的常量表达式不同,可以是变量表达式。
    new运算符申请内存失败时返回nullptr,申请一个动态数组往往需要一个较大的空间,因此在程序中需要使用new的返回值进行判断,看是否申请内存成功。

例②:

	int* pa;
	pa = new int[5];	//pa指向5个未初始化的int型数据对象的首地址
	//如果想要将pa在创建时就初始化好应改为如下代码
	pa = new int[5]{ 1,2,3,4};	//此时第一个int型的对象的值就为1,同理后面的对象依次是{}中给出的值
	//当{}中给初的数值的个数小于创建的对象个数时,会将其值默认初始化为0
	//也可以使用一条语句定义
	int*pa=new int[5];
	//如果像将其初始化则像上述代码一样修改即可

结果如下:
在这里插入图片描述

★注意

(1)用new运算符申请分配的内存空间必须用delete释放。
(2)delete作用的指针必须是由new分配内存空间的首地址。
(3)对于一个已分配内存的指针,只能用delete释放一次。
(4)newdelete运算实现了堆空间的动态分配,它在带来方便的同时也潜伏了可能的 隐患:使用new进行内存分配之后,忘记了使delete运算进行内存回收,即“内存泄露”,如 果程序长时间运行,则有可能因内存耗尽而使系统崩溃,所以对newdelete要养成配对使用的良好习惯。

delete 运算

当程序不需要由new分配的内存空间时,可以用delete释放这些空间。其语法格式如下:
delete 指针变量名;
如果删除的是动态数组,则语法格式如下:
delete[]指针变量名;
其中:

  • 括号[]表示用delete释放为多少个对象分配的地址,[]中不需要说明对象的个数。
  • 不管建立的动态数组是多少维,释放的格式都是一样的。

对于例①、②分配的空间,释放语句如例③一样:
例③:

	delete pi;
	delete []pa;

例④:

class Obj 
{ 
public: 
	 Obj(void); // 无参数的构造函数
	 Obj(int x); // 带一个参数的构造函数 

} 
void Test(void) 
{ 
	 Obj *a = new Obj; 
	 Obj *b = new Obj(1); // 初值为 1 
	 delete a; 
	 delete b; 
} 

如果用 new 创建对象数组,那么只能使用对象的无参数构造函数。例如

 Obj *objects = new Obj[100]; // 创建 100 个动态对象 

不能写成

Obj *objects = new Obj[100] (1);// 创建 100 个动态对象的同时赋初值 1 

在用 delete 释放对象数组时,留意不要丢了符号‘[]’。例如

delete []objects; // 正确的用法 
delete objects;  // 错误的用法 

后者相当于 delete objects[0],漏掉了另外 99 个对象。

面试题

一、malloc/free和new/delete的区别

  1. malloc和free函数new和delete操作符
  2. malloc申请的空间不会初始化,new可以初始化。
  3. malloc申请空间时,需要手动计算空间大小并传递,new只需在其后跟上空间的类型即可。
  4. malloc的返回值为void*, 在使用时必须强制类型转换new不需要,因为new后跟的是空间的类型。
  5. malloc申请空间失败时,返回的是NULL,因此使用时必须判空,new不需要,但是new需要捕获异常。
  6. 申请自定义类型对象时,malloc/free只会开辟空间,不会调用构造函数与析构函数,而new在申请空间后会调用构造函数完成对象的初始化,delete在释放空间前会调用析构函数完成空间中资源的清理。

二、如何一次在堆上申请4G的内存?

在32位平台下mallocnew最大能申请2GB左右的内存。
只需把我们的环境改成64位平台下即可申请成功4GB的内存。
在64位平台下最大能申请的内存大小约为160亿GB左右
在这里插入图片描述
END...

评论 14
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值