cpp--内存管理(new/delete的用法),超详细讲解,一看就会!

cpp--内存管理(new/delete的用法),超详细讲解,一看就会!

  • c/c++内存管理
    • 1. c语言中动态内存管理方式
    • 2. c++的内存管理方式
      • 2.1 new/delete操作内置类型
      • 2.2 new/delete操作自定义类型
    • 3. malloc/free和new/delete的区别

c/c++内存管理

1. c语言中动态内存管理方式

void Test ()
{
int* p1 = (int*) malloc(sizeof(int));
free(p1);

// 1.malloc/calloc/realloc的区别是什么? calloc = malloc + memset(初始化)
int* p2 = (int*)calloc(4, sizeof (int));
int* p3 = (int*)realloc(p2, sizeof(int)*10);

// 这里需要free(p2)吗? 不用,原地扩容 p2 = p3;
free(p3 );
}

主要区别总结

  1. 初始化方面
    malloc 分配的内存块内容是未初始化的,其中的值是不确定的。
    calloc 会将分配的内存块初始化为零,这在需要使用零值初始化的场景下非常方便,如初始化数组。
  2. 参数方面
    malloc 只需要一个参数,即要分配的内存大小(字节数)。
    calloc 需要两个参数,分别是元素的数量和每个元素的大小,通过这两个参数计算出总的内存分配大小。
    realloc 需要一个指向已分配内存块的指针和新的内存大小。
  3. 用途方面
    malloc 适用于需要动态分配内存,但不需要对内存进行初始化的场景。
    calloc 适用于需要动态分配内存并初始化为零的场景,例如初始化数组或结构体。
    realloc 适用于需要调整已分配内存块大小的场景,比如根据程序运行时的需求动态增加或减少内存使用量。

2. c++的内存管理方式

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

2.1 new/delete操作内置类型

#include 
using namespace std;
int main()
{
	int* p2 = (int*)malloc(sizeof(int));
	// 自动计算大小,不需要强转 
	int* p3 = new int;//动态申请一个int类型的空间

	int* p4 = (int*)malloc(sizeof(int)*10);
	int* p5 = new int[10];//动态申请10个int类型的空间

	free(p2);
	free(p4);

	delete p3;//删除动态申请一个int类型的空间
	delete[] p5;//删除动态申请的n个xx类型的空间

	// 额外支持开空间+初始化
	//动态申请一个int类型的空间并初始化为10
	int* p6 = new int(10);
	//动态申请10个int类型的空间并将前三个空间分别初始化为1,2,3
	//其余均初始化为0
	int* p7 = new int[10]{1,2,3};
	//动态申请10个int类型的空间并初始化为0
	int* p8 = new int[10]{};

	return 0;
}

注意:申请和释放单个元素的空间,使用new和delete操作符,申请和释放连续的空间,使用new[]和delete[],一定要匹配起来使用!!!

2.2 new/delete操作自定义类型

#include 
using namespace std;
class A
{
public:
	A(int a = 0)
		:_a(a)
	{
		cout << "A()" << endl;
	}
	~A()
	{
		cout << "~A()" << endl;
	}
private:
	int _a;
};
int main()
{
	A* p1 = new A(1);
	delete p1;

	A* p2 = new A[10]{3,2,1};
	delete[] p2;

	return 0;
}

cpp--内存管理(new/delete的用法),超详细讲解,一看就会!_第1张图片

cpp--内存管理(new/delete的用法),超详细讲解,一看就会!_第2张图片

#include 
using namespace std;
class A
{
public:
	A(int a = 0)
		:_a(a)
	{
		cout << "A()" << endl;
	}
	~A()
	{
		cout << "~A()" << endl;
	}
private:
	int _a;
};
int main()
{
	A* p1 = new A(1);
	delete p1;
	cout << "-------------------------" << endl;
	A* p2 = new A[5]{3,2,1};
	delete[] p2;
	cout << "-------------------------" << endl;
	A aa1(1);
	A aa2(2);
	A aa3(3);
	A* p3 = new A[5]{ aa1, aa2, aa3 };
	delete[] p3;
	cout << "-------------------------" << endl;
	//创建临时对象 A(1)、A(2)、A(3),调用 3 次构造函数。
	//使用 new A[5]{ A(1), A(2), A(3) } 创建一个包含 5 个 A 类对象的数组,
	// 前 3 个对象通过拷贝临时对象来初始化,后 2 个对象使用默认值初始化,
	// 共调用 5 次构造函数。创建临时对象调用的 3 次构造函数也算在内,
	// 所以这部分总共调用 8 次构造函数
	A* p4 = new A[5]{ A(1), A(2), A(3)};
	delete[] p4;
	cout << "-------------------------" << endl;

	return 0;
}

以前我们构造链表时经常会使用malloc,现在我们可以使用new来构造链表了!

#include 
using namespace std;
class ListNode
{
	friend void PrintList(ListNode* head);
	friend ListNode* createlist();
public:
	ListNode(int data = 0)
		:_data(data)
		, _next(nullptr)
	{
		cout << "ListNode(int data = 0)" << endl;
	}
private:
	int _data;
	ListNode* _next;
};
ListNode* createnode(int data)
{
	ListNode* node = new ListNode(data);//动态申请一个ListNode类型的空间并初始化为data
	return node;
}
void PrintList(ListNode* head)
{
	ListNode* cur = head;
	while (cur)
	{
		cout << cur->_data << " ";
		cur = cur->_next;
	}
}
ListNode* createlist()
{
	int n = 0;
	cin >> n;
	int data = 0;
	ListNode* head = NULL;
	ListNode* tail = NULL;

	for (int i = 0; i < n; i++)
	{
		cin >> data;
		ListNode* newnode = createnode(data);
		if (head == NULL)
		{
			head = newnode;
			tail = head;
		}
		else
		{
			tail->_next = newnode;
			tail = tail->_next;
		}
	}

	return head;
}
int main()
{
	int n = 0;
	ListNode* head = createlist();
	PrintList(head);
}

cpp--内存管理(new/delete的用法),超详细讲解,一看就会!_第3张图片

注意: 在申请自定义空间时new会调用构造函数,delete会调用析构函数,而malloc与free不会

3. malloc/free和new/delete的区别

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在释放空间前会调用析构函数完成空间中资源的清理

你可能感兴趣的:(c++,开发语言,c++)