malloc/calloc/realloc函数的区别及用法

malloc/calloc/realloc函数的区别及用法

  • 1.malloc函数
  • 2.calloc函数
  • 3.realloc函数

malloc/calloc/realloc函数都是分配内存,但是也存在一定的差异。

1.malloc函数

malloc函数文档
函数原型:void* malloc (size_t size);
返回值: 成功时指向由函数分配的内存块指针,此指针的类型总是void*,该数据指针可以转换为所需类型的数据指针(如下例的int类型),以便可以解除引用。如果函数未能分配请求的内存块,则空指针会被归还。
参数:size为要申请的空间大小,需要我们计算。如:
int *p=(int*) malloc(10 * sizeof (int)),如果编译器默认int为4字节的话,那么10个int类型的空间大小就是40字节。一次性申请40字节的连续空间,并将空间基地址强转为int类型,赋值给指针p,此时内存里存放的值是不确定的。

2.calloc函数

calloc函数文档
函数原型:void* calloc (size_t num, size_t size);
返回值: 成功时指向由函数分配的内存块指针,此指针的类型总是void*,该数据指针可以转换为所需类型的数据指针(如下例的int类型),以便可以解除引用。如果函数未能分配请求的内存块,则空指针会被归还。
参数:num为要分配的元素数,size为每个元素的大小。 其比malloc函数多了一个参数num,省去了需要人为计算所申请空间大小。比如要申请10个int类型的空间:int *p = (int *)calloc(10, sizeof (int))

calloc函数与malloc函数最大的区别是:malloc申请后空间的值是随机的,并没有进行初始化,而calloc却在申请后,对空间逐一进行初始化,并设置值为0。

#include
using namespace std;
int main() {
	int* p = (int*)malloc(10 * sizeof(int));
	int* pp = (int*)calloc(10, sizeof(int));
	int i;
	cout<<"malloc申请的空间的值:"<<endl;
	for (i = 0; i < 10; i++)
		cout<<*p++<<" ";
	cout << endl;
	cout<<"calloc申请的空间的值:"<<endl;
	for (i = 0; i < 10; i++)
		cout<<*pp++<<" ";

	cout << endl;
	return 0;
}

在这里插入图片描述

既然calloc不需要计算空间并且可以直接初始化内存避免错误,那为什么不直接使用calloc函数,malloc函数还有什么用呢?

主要原因就是效率。calloc函数由于给每一个空间都要初始化值,那必然效率比malloc要低,并且实际应用中,很多情况的空间申请是不需要初始值的,这也就是为什么许多初学者更多的接触malloc函数的原因。

3.realloc函数

realloc函数和上面两个有本质的区别,它用于对动态内存进行扩容(及已申请的动态空间不够使用,需要进行空间扩容操作)。
函数原型:void* realloc (void* ptr, size_t size);
返回值: 指向重新分配的内存块的指针,该指针可以是ptr或者一个新的地点。此指针的类型为void*,该数据指针可以转换为所需类型的数据指针,以便可以解除引用。
参数:ptr为指向原来空间基址的指针, size为接下来需要扩充容量的大小。

#include
using namespace std;
int main() {
	int* p = (int*)malloc(10 * sizeof(int));
	int* pp = (int*)realloc(p, 40 * sizeof(int));
	cout << "原来的p_Address: " << p << "  " << "扩容后的pp_Address: " << pp << endl;
	return 0;

}

扩容后地址和原先地址是不一样的,但是这仅仅取决于扩容的内存大小。
在这里插入图片描述

实际上:

  1. 如果size较小,原来申请的动态内存后面还有空余内存,系统将直接在原内存空间后面扩容,并返回原动态空间基地址;
#include
using namespace std;
int main() {
	int* p = (int*)malloc(10 * sizeof(int));
	int* pp = (int*)realloc(p, 14 * sizeof(int));
	cout << "原来的p_Address: " << p << "  " << "扩容后的pp_Address: " << pp << endl;
	return 0;

}

在这里插入图片描述

  1. 如果size较大,原来申请的空间后面没有足够大的空间扩容,系统将重新申请一块(20+size)*sizeof(int)的内存,并把原来空间的内容拷贝过去,原来空间free;如果size非常大,系统内存申请失败,返回NULL,原来的内存不会释放。

注意:如果扩容后的内存空间比原空间小,将会出现数据丢失,如果直接realloc(p, 0),相当于free(p)

你可能感兴趣的:(C++)