动态内存管理

1.C的动态内存管理细节

C语言中,使用malloc/calloc/realloc/free进行动态内存管理

malloc():接受一个参数——所需内存字节。分配内存后,返回那块内存的第一个字节的地址,用指针变量来接收。所以,传统上将malloc()定义为指向char的指针类型。函数malloc()可用来返回数组指针、结构指针等等。如果malloc()找不到所需的空间,它将返回空指针。


  
  
#include<iostream> #include<cstdio>
double* ptr = (double*)malloc(30 * sizeof(double)); void *malloc(size_t size);//函数原型

calloc():在内存的动态存储区中分配n个长度为size的连续空间,函数返回一个指向分配起始地址的指针;如果分配不成功,返回NULL。它与malloc()函数不同的是——calloc在动态分配完内存后,自动初始化该内存空间为零,而malloc不初始化,里边数据是随机的垃圾数据。

long* newmem = (long*)calloc(100, sizeof(long));
void *calloc(size_t n, size_t size);//函数原型

realloc():先判断当前的指针是否有足够的连续空间,如果有,扩大mem_address指向的地址,并且将mem_address返回,如果空间不够,先按照newsize指定的大小分配空间,将原有数据从头到尾拷贝到新分配的内存区域,而后释放原来mem_address所指内存区域(注意:原来指针是自动释放,不需要使用free),同时返回新分配的内存区域的首地址。即重新分配存储器块的地址。

long* newm = (long*)realloc(newmem, sizeof(long)* 4);
void *realloc(void *memblock, size_t size);//函数原型

free():释放malloc(或callocrealloc)函数给指针变量分配的内存空间的函数使用后该指针变量一定要重新指向NULL,防止野指针出现,有效 规避误操作。它可以防止内存泄漏。

#include<iostream>
#include<cstdio>

int main()
{
	double* ptr = (double*)malloc(30 * sizeof(double));
	void *malloc(size_t size);//函数原型


	long* newmem = (long*)calloc(100, sizeof(long));
	void *calloc(size_t n, size_t size);//函数原型

	long* newm = (long*)realloc(newmem, sizeof(long)* 4);
	void *realloc(void *memblock, size_t size);//函数原型

	free(newm);
	free(ptr);
	void free(void *memblock);//函数原型
}

2.C动态管理在C++中的缺陷引入C++动态内存管理

1,malloc与free是C++/C语言的标准库函数,new/delete是C++的运算符。它们都可用于申请动态内存和释放内存。
2,对于非内部数据类型的对象而言,光用maloc/free无法满足动态对象的要求。对象在创建的同时要自动执行构造函数,对象在消亡之前要自动执行析构函数。由于malloc/free是库函数而不是运算符,不在编译器控制权限之内,不能够把执行构造函数和析构函数的任务强加于malloc/free。
3,因此C++语言需要一个能完成动态内存分配和初始化工作的运算符new,以一个能完成清理与释放内存工作的运算符delete。注意new/delete不是库函数。

4,C++程序经常要调用C函数,而C程序只能用malloc/free管理动态内存。

5、new可以认为是malloc加构造函数的执行。new出来的指针是直接带类型信息的。而malloc返回的都是void指针。

3.C++动态内存管理基本语法和使用

C++通过new和delete动态管理内存。
new/delete动态管理对象。
new[]/delete[]动态管理对象数组。

#include<iostream>
using namespace std;

int main()
{
	//new是操作符,delete是操作符,int是类型,(3)代表了初始化为3,[3]代表了对象个数	
	
	int* p1 = new int;     //动态分配4个字节(1个int)的空间单个数据
	int* p2 = new int(3);  //动态分配4个字节(1个int)的空间并初始化为3
	int* p3 = new int[3];  //动态分配12个字节(3个int)的空间

	delete p1;
	delete p2;
	delete[] p3;
}

4.C++提供的动态内存管理的底层实现及其接口operator new/delete/new[]/delete[]

我们通常讲的new是指的是new operator。        

我们在使用new operator的时候,实际上是执行了两个步骤:

1)调用operator new分配内存 ;2)调用构造函数生成类对象;

我们通常讲的delete是指的是delete operator。        

我们在使用delete operator的时候,实际上是执行了两个步骤:

1)调用析构函数 ;2)调用operator delete释放内存;

void Test()
{
	Array* p1 = (Array*)malloc(sizeof(Array));
	Array* p2 = new Array;
	Array* p3 = new Array(20);
	Array* p4 = new Array[10];

	free(p1);
	delete p2;
	delete p3;
	delete[] p4;
}

调试过程:

1)

	Array(size_t size = 10)
		:_size(size)
		, _a(0)
	{
		cout << "Array(size_t size)" << endl;
		if (_size > 0)
		{
			_a = new int[size];
		}
	}

2)

// newaop -- operator new[](size_t) REPLACEABLE
#include <new>

void *__CRTDECL operator new[](size_t count) _THROW1(std::bad_alloc)
	{	// try to allocate count bytes for an array
	return (operator new(count));
	}

5.定位new表达式

定位new表达式是在已分配的原始内存空间中调用构造函数初始化一个对象。
new (place_address) type
new (place_address) type(initializer-list)
place_address必须是一个指针,initializer-list是类型的初始化列表。

#include<iostream>
using namespace std;

class Array
{
public:
	Array(size_t size = 10)
		:_size(size)
		, _a(0)
	{
		cout << "Array(size_t size)" << endl;
		if (_size > 0)
		{
			_a = new int[size];
		}
	}

	~Array()
	{
		cout << "~Array()" << endl;
		if (_a)
		{
			delete[]_a;
			_a = 0;
			_size = 0;
		}
	}
    
private:
	int* _a;
	size_t _size;
};

void Test()
{
	Array* p1 = (Array*)malloc(sizeof(Array));//malloc/free+定位操作符new()/显示调用析构函数,模拟new和delete的行为
	new(p1)Array(100);

	p1->~Array();
	free(p1);

	Array* p2 = (Array*)malloc(sizeof(Array)* 10);//malloc/free+定位操作符new()/显示调用析构函数,模拟new[]和delete[]的行为
	for (int i = 0; i < 10; ++i)
	{
		new(p2 + i)Array;
	}

	for (int i = 0; i < 10; ++i)
	{
		p2[i].~Array;
	}
	free(p2);
}

int main()
{
	Test();
	return 0;
}

6.delete[] 析构函数调用细节剖析










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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值