C++的内存管理。

本文深入探讨C++中的内存管理技巧,包括C语言中的内存管理回顾,C++中的new和delete操作符详解,以及如何设计具有特殊内存需求的类。文章通过实例展示了不同内存管理方法的特点和使用场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

今天我们来学习有关C++的内存管理。

一。首先让我们先回忆一下C语言中的内存管理

1.在C语言中,我们经常用malloc、calloc以及realloc。

举例:

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)malloc只是开辟空间没有初始化、calloc在开辟空间的同时也进行了初始化为0。realloc可以扩大空间,修改已经开辟好的空间大小。

(2)在开辟空间的同时,必须记得要释放空间,否则会产生内存泄漏。内存泄漏简单来说就是用户向系统借来了空间,最后结束时就必须还给系统,若不还,会导致程序崩溃。

二。C++内存管理

1.在C++中,会用new和delect来进行动态内存管理。

(1)new/delete动态管理对象。

(2)new[]/delete[]动态管理对象数组。

(3)举例:

void Test ()
{
 // 动态分配4个字节(1个 int)的空间单个数据
 int* p4 = new int;

 // 动态分配4个字节(1个 int)的空间并初始化为3
 int* p5 = new int(3);

 // 动态分配12个字节(3个 int)的空间
 int* p6 = new int[3];

 delete p4 ;                //只要用new开辟空间,就一定要用delete释放空间。
 delete p5 ;
 delete[] p6 ;
}

2。new/delete操作符/操作符new/delete。

(1) 操作符new与delete 操作符new/delete是一个函数:

void * operator new (size_t size);

void operator delete (void * );

void * operator new [](size_t size);

void operator delete[] (void*);

(2)他们只负责分配空间/释放空间,不会调用对象构造函数/析构函数来初始化/清理对象> ,实际operator new 和operator delete只是malloc和free的一层封装。

(3)

new做了两件事 1. 调用operator new分配空间。 2. 调用构造函数初始化对象。

delete也做了两件事 1. 调用析构函数清理对象 2. 调用operator delete释放空间

new[N] 1. 调用operator new分配空间。 2. 调用N次构造函数分别初始化每个对象。

delete[] 1. 调用N次析构函数清理对象。(思考这里怎么N是怎么来的?) 其实是编译器在new出的数组对象头指 针位置向前4个字节中记录了对象个数(4个字节对应一个int值),结合内存变化观察下这种情况。 2. 调用operator delete 比释放空间。

3.定位new表达式

(1)已分配的原始内存空间中调用构造函数初始化一个对象。

(2)函数。

new (place_address) type

new (place_address) type(initializer-list)

place_address必须是一个指针,initializer-list是类型的初始化列表。

(3)调用:

allocator alloc;

T * ptr1 = alloc.allocate(1);//从池对象中申请对象对应的空间, T为对象类型 。

new(ptr1)T;//显式调用T类型的构造函数进行初始化

ptr1->~T();

alloc.deallocate(ptr1,1)

(4)举例:

class stu
{
public:
	stu()
	{
		cout<<"stu()"<<a<<endl;
	}
	~stu()
	{
		cout<<"~stu()"<<endl;
	}
private:
	int* a;
};

int main()
{
	allocator<stu> alloc;
	stu * ptr1 = alloc.allocate(1);//从池对象中申请对象对应的空间, stu为对象类型
	new(ptr1)stu;//显式调用stu类型的构造函数进行初始化

	ptr1->~stu();
	alloc.deallocate(ptr1,1);
	system("pause");
	return 0;
}

(5)应用场景:多用于对象池化处理。最常见的就是内存池技术。 对象池化:将用过的对象保存起来,等下一次需要这种对象的时候,再拿出来重复使用,从而在一定程度上减少频 繁创建对象所造成的开销。用于充当保存对象的“容器”的对象,被称为“对象池”。

4.new/delete与malloc/free的区别与联系:

(1)它们都是动态管理内存的入口。

(2)malloc/free是C/C++标准库的函数,new/delete是C++操作符。

(3)malloc/free只是动态分配内存空间/释放空间。而new/delete除了分配空间还会调用构造函数和析构函数进 行初始化与清理(清理成员)。

(4)malloc/free需要手动计算类型大小且返回值会void*,new/delete可自己计算类型的大小,返回对应类型的指针。

三。特殊要求的类的设计:

在设计之前我们要先知道一件事:

在C++中,类的对象建立分为两种,一种是静态建立,如A a;另一种是动态建立,如A* ptr=new A;这两种方式是有区别的。

(1)静态建立一个类对象,是由编译器为对象在栈空间中分配内存,是通过直接移动栈顶指针,挪出适当的空间,然后在这片内存空间上调用构造函数形成一个栈对象。使用这种方法,直接调用类的构造函数。

(2)动态建立类对象,是使用new运算符将对象建立在堆空间中。这个过程分为两步,第一步是执行operator new()函数,在堆空间中搜索合适的内存并进行分配;第二步是调用构造函数构造对象,初始化这片内存空间。这种方法,间接调用类的构造函数。

1.一个类只能在堆上实现创建。

(1)分析:因为只能在堆上实现,所以当我们把析构函数设为私有成员后,编译器就不会再使用构造函数创建对象,所以此时只能用new在堆上创建。

class stu
{
public:
	stu()
	{
		cout<<"stu()"<<endl;
	}
private:
	~stu()
	{
		cout<<"~stu()"<<endl;
	}
private:
	int a;
};

int main()
{
	//stu a;               //无法直接初始化,因为析构函数为私有的。
	stu* b=new stu;
	system("pause");
	return 0;
}

这样就可以在堆上创建了,但是这也有一个问题,那就是没有释放,所以还可以优化为:

class stu
{
public:
	static stu* creat()
	{
		stu* b=new stu;
		b->a=10;
		cout<<"stu()"<<endl;
		return b;
	}

	static void destory(stu* b)
	{
		if(b)
		{
			delete(b);
			b=NULL;
		}
		cout<<"~stu()"<<endl;

	}
	int a;
private:
	stu(){};
	~stu(){};
};

2.只能在栈上实现创建类。

(1)分析:要想实现只在栈上创建,那就要让new函数不能只用,所以将new函数设为私有函数即可。

(2)

class A
{
public:
	A()
	{
		cout<<"Creat OK!"<<endl;
	}
	~A()
	{
		cout<<"delete ok!"<<endl;
	}
private:
	void* operator new(size_t size);
	void operator delete(void *p);
};

3.请设计一个类,该类只能创建一个对象。

(1)弄一个判别函数和一个静态成员变量,判别函数判别那个变量是否重复,若重复直接返回,否则直接返回那个变量。

(2)

class AA
{
public:
	static AA* get()
	{
		if(a==NULL)
		{
			a=new AA();
		}
		return a;
	}
	static void destroy()
	{
		if(a!=NULL)
		{
			delete(a);
		}
		a=NULL;
	}
private:
	AA()
	{
		cout<<"++++++++++"<<endl;
	}
	static AA* a;
};
AA* AA::a=NULL;           

以上就是C++的内存管理。

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值