malloc、calloc、free和new、delete和memset、memcpy

一. malloc、calloc、free

  • malloc原型:void* malloc(unsigned int size)
  • calloc原型:void* calloc(size_t numElements, size_t sizeOfElement)
  • 两个函数返回值均为系统分配的地址,失败返回NULL
  • malloc的参数size是需要内存空间的长度:
char* p;
p=(char*)malloc(20*sizeof(char));
  • calloc第一个参数是元素个数,第二个是地址单位元素长度:
char* p;
p=(char*)calloc(20,sizeof(char));
  • malloc和calloc一个很重要的区别是:malloc分配后的空间里是随机值,而calloc会初始化为0
#include<iostream>
#include<cstdlib>
using namespace std;

int main() {
	int *c_p, *m_p;
	m_p = (int*)malloc(10 * sizeof(int));
	c_p = (int*)calloc(10, sizeof(int));
	cout << "malloc: ";
	for (int i = 0; i < 10; i++)
		cout  << m_p[i] << " ";
	cout << endl << "calloc: ";
	for (int i = 0; i < 10; i++)
		cout  << c_p[i] << " ";
	cout << endl;
	getchar();
	return 0;
}

  • realloc原型:void* realloc(void *ptr, size_t new_Size) 
  • realloc用于对动态内存进行扩容(及已申请的动态空间不够使用,需要进行空间扩容操作)。ptr为指向原来空间基址的指针, new_size为接下来需要扩充容量的大小。
  • 分以下三种情况:
    ①如果size较小,原来申请的动态内存后面还有空余内存,系统将直接在原内存空间后面扩容,并返回原动态空间基地址。
    ②如果size较大,原来申请的空间后面没有足够大的空间扩容,系统将重新申请一块(20+size)*sizeof(int)的内存,并把原来空间的内容拷贝过去,原来空间free。
    ③如果size非常大,系统内存申请失败,返回NULL,原来的内存不会释放。
  • 示例:
#include<iostream>
#include<cstdlib>
using namespace std;

int main() {
	int *p, *r_p;
	p = (int*)malloc(10 * sizeof(int));
	r_p = (int*)realloc(p, 100);
	cout << "p: " << p << endl << "r_p: " << r_p << endl;

	getchar();
	return 0;
}

  • free的调用形式为free(void*ptr):释放ptr所指向的一块内存空间。 malloc和calloc申请的空间都要free,防止泄露。记得释放后把ptr指向NULL,避免野指针。
  • malloc最大分配空间:
    64位的,操作系统保留一部分内存(大概2G),还有差不多6G可以申请。32位可分配大致2G不到的内存(32位最大可识别内存4G,除去系统保留就是不到2G)。
    另外,程序是32位或者是64位并不是由你的操作系统决定,而是编译器决定,准确的说是决定于编译器和编译选项,64位系统照样可以跑32位的程序。

二. new、delete

  • 只要告诉new为哪种数据类型分配内存,new会找到一个正确的内存块并返回指针:
int *p = new int;
  • 使用delete会释放指针指向的内存,但不会删除指针本身。
delete p;
  • new和delete要成对使用,防止内存泄露。
  • 下面两种情况注意:
//delete只能用于new分配的内存,因此下面这么做是不可以的
int test=5;
int *p=&test;
delete p;

//但这么做是可以的
int *p=new int;
int *ps=p;
delete ps;
  • 使用new时,可以在运行阶段根据需求建立数组。被称为动态联编,数组也叫动态数组。
int *p = new int[10];

delete [] p;
  • malloc和new的区别:
    ①malloc/free是库函数,而new和delete是C++的操作符。
    ②一个很大的区别是,malloc只负责分配内存,而new在分配后会调用默认构造函数,delete会调用默认析构函数。或者new还可以调用自定义的构造函数。因此malloc比较适合内部数据类型,对非内部数据动态对象,不太好初始化和销毁。
    ③上面提到的能否在运行时动态建立数组。
  • 不能连续delete或者free一个指针,但delete和free对空指针操作不会出错。
  • C++允许重载new/delete操作符,特别的,布局new的就不需要为对象分配内存,而是指定了一个地址作为内存起始区域,new在这段内存上为对象调用构造函数完成初始化工作,并返回此地址。而malloc不允许重载。

三. memset和memcpy

  • 原型: void *memset(void *s, int ch, size_t n) 其中:
    s:为指针或是数组
    ch:是赋给buffer的值
    n:长度,要用sizeof(type)*num
  • 功能:将s所指向的某一块内存中的前n个字节的内容全部设置为ch指定的ASCII值, 第一个值为指定的内存地址,块的大小由第三个参数指定,这个函数通常为新申请的内存做初始化工作, 其返回值为指向s的指针,它是对较大的结构体或数组进行清零操作的一种最快方法。
    头文件是:<memory.h>或<string.h>
  • 注意:memset是一个一个字节初始化的,char的话本身为一个字节。但像int之类的,如果不是初始化为0,可能不是你想要的结果。
  • 原型:void *memcpy(void*dest, const void *src, size_t n);
  • 功能:由src指向地址为起始地址的连续n个字节的数据复制到以destin指向地址为起始地址的空间内。返回一个指向dest的指针。
    #include<string.h>
  • 注意:
    ①source和destin所指内存区域不能重叠。
    ②与strcpy相比,memcpy并不是遇到'\0'就结束,而是一定会拷贝完n个字节。
    ③如果目标数组destin本身已有数据,执行memcpy()后,将覆盖原有数据(最多覆盖n)。

猜你喜欢

转载自blog.csdn.net/weixin_39731083/article/details/82343511