[C++]new和delete进行动态分配和撤销存储空间

本文详细介绍了C++中的new和delete运算符用于动态内存分配和释放的过程,以及它们与C语言malloc和free的区别,特别强调了new对基本类型和自定义类型的不同处理方式,包括构造函数和析构函数的调用。此外,还讨论了new[]和delete[]用于数组的内存操作,以及如何使用定位new进行初始化和手动析构释放内存。
摘要由CSDN通过智能技术生成

        在C语言中我们可以利用库函数mallocfree来分配和撤销内存空间。C++提供了较简便而功能较强的运算符newdelete来取代mallocfree函数。注意:newdelete是运算符,不是函数,因此执行效率高。

一、newdelete

        对于申请和释放单个变量的内存空间,我们可以使用new和delete运算符来实现。

new运算符的使用一般格式为:

        new 类型(初值); 

delete运算符的使用格式为:

        delete 指针变量

(一)基本类型

        下面是用newdelete基本类型动态分配和撤销内存的例子:

//new 和 delete
int main()
{
	//开辟空间
	int* ptr1 = new int;//开辟一个存放一个整形大小的空间并返回其首地址赋值给ptr1
	int* ptr2 = new int(10);//开辟一个存放一个整形大小的空间并将其用10进行初始化

	cout << "*ptr1 = " << *ptr1 << endl;
	cout << "*ptr2 = " << *ptr2 << endl;

	//释放空间
	delete ptr1;
	delete ptr2;
	return 0;
}

运行结果:

     newdelete对基本类型的动态分配内存和释放内存和C语言mallocfree差不多,但是比C语言下函数的好用和方便,因为C语言返回指向内存的指针时,需要我们对其返回值进行检查,如果为NULL则代表动态内存分配失败,需要进行特殊处理,但我们的C++中的new运算符进行动态分配内存则不需要考虑这个问题。我们在使用new时,其实调用了全局函数operate new,而operate new里封装有malloc,所以C++动态分配内存的底层还是使用malloc来分配空间,operate new里已经对分配内存失败时做出了处理,所以不需要像C语言那样手动处理内存分配失败的情况。

(二)自定义类型

        上面对于基本类型使用newdelete动态分配和释放内存和C语言的使用mallocfree没多大区别,但是对于自定义类型,new在对对象动态分配内存时会调用其构造函数,而使用malloc只是开辟一段内存空间,但并不会为开辟的对象调用其构造函数进行初始化。而相应的,delete会先调用对象的析构函数,进行对资源的释放,再调用全局函数operate delete来释放存储类的对象的空间。

        

//new自定义类型
class A
{
private:
	int _a;
public:
	A(int a = 0,int b = 0):_a(a)
	{
		cout << "a = " << a << " b = " << b << endl;
	}

	~A()
	{
		cout << "~A()" << endl;
	}
};

int main()
{
	//开辟空间
	A* pa1 = new A;//对自定义类型A动态分配内存,并且调用其构造函数
	A* pa2 = new A(1);//调用构造函数时传入单个参数进行初始化

	//如果调用构造函数需要传入多个参数,则使用{参数列表}
	A* pa3 = new A{ 1,2 };
	A* pa4 = new A{ 3,4 };

	//释放动态分配的自定义类型的空间
	delete pa1;
	delete pa2;
	delete pa3;
	delete pa4;
	return 0;
}

运行结果: 

        我们可以看到,如果动态分配内存的变量为自定义类型,我们可以传入对应的参数来调用构造函数来进行初始化,这个时候new的用法就变成了: 

                new 自定义类型{初始化列表...}

二、new T[]和delete[]

        对于申请和释放数组的内存空间,我们需要使用new T[]和delete[]运算符来实现。

 申请数组空间的方法为:

        new 类型名[数组的大小]{初始化列表...}

释放数组空间的方法:

        delete[] 指针变量 

(一)基本类型

//遍历数组
void Print(int* arr, int size)
{
	for (int i = 0; i < size; i++)
	{
		cout << arr[i] << " ";
	}
	cout << endl;
}

//开辟数组空间
int main()
{
	//为数组开辟空间
	int* parr1 = new int[10];//申请元素个数为10的数组的内存空间
	int* parr2 = new int[10] {1,2,3,4,5};//在申请数组空间后并对其初始化,
	//若未完全初始化,则剩下的编译器将会用0进行初始化

	//遍历数组
	Print(parr1, 10);
	Print(parr2, 10);

	//释放空间
	delete[] parr1;
	delete[] parr2;
	return 0;
}

运行结果:

(二)自定义类型

        对于自定义类型的数组:

class A
{
private:
	int _a;
public:
	A(int a = 0,int b = 0):_a(a)
	{
		cout << "a = " << a << " b = " << b << endl;
	}

	~A()
	{
		cout << "~A()" << endl;
	}
};

//开辟自定义类型的数组
int main()
{
	//申请元素个数为10的自定义类型的数组
	A* parr1 = new A[10]{ {1,2},{3,4} };//用参数对其前两个对象进行初始化

	//释放自定义类型
	delete[] parr1;
	return 0;
}

运行结果: 

        

        可以看到,我们调用delete[]时,对其每个自定义类型的对象调用了一次析构函数进行资源的释放。 

三、定位new

        在用malloc对对象进行内存申请时,只能为对象申请空间,但不能随之调用其构造函数对对象进行初始化构造函数不能够被对象显式调用,只能在创建对象的时候调用其构造函数,但是定位new可以实现malloc自定义类型申请原始的内存空间后用定位new手动调用其对象的构造函数来初始化成一个对象,相当于实现运算符new的效果。因为对象的析构函数可以被手动调用,所以在调用了对象的析构函数后再用free来释放其对象的内存,这样可以达到运算符delete的效果。

定位new的一般使用方法:

        new(指针变量)类型名{参数列表...}

下面时使用定位new调用对象的构造函数的实例:

class A
{
private:
	int _a;
public:
	A(int a = 0,int b = 0):_a(a)
	{
		cout << "a = " << a << " b = " << b << endl;
	}

	~A()
	{
		cout << "~A()" << endl;
	}
};

//定位new手动调用构造函数
int main()
{
	//用malloc开辟一段自定义类型A的大小的内存空间
	//此时对象指针指向的只是一段内存,并不能称为对象,需要显式调用其构造函数
	A* parr1 = (A*)malloc(sizeof(A));
	//定位new new(指针变量)类型名{参数列表...}
	new(parr1)A(1,2);

	//模拟delete的功能,用free释放A的对象
	parr1->~A();//显式调用A的析构函数
	free(parr1);

	return 0;
}

运行结果:

四、 关于扩容

        在C++中,并没有C语言realloc可以对已开辟的内存空间进行扩容运算符。但是我们如果真的需要扩容,最简单的方法就是手动扩容:先开辟一段要扩容的大小的新的内容空间,然后用memcpy函数将其旧的内存空间里的数据拷贝到这个新开辟的内存空间中,然后再释放掉旧的内存空间。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值