在内存四区中我们能手动申请的只有堆区空间,栈区、全局区和代码区都是自动分配和释放。在C语言中我们使用malloc(),realloc(),calloc()函数来进行对堆空间进行分配内存并且他们的返回值都是指向这块内存空间的指针,通过free()对堆空间进行释放。
成功时,返回指向新分配内存的指针。为避免内存泄漏,必须用free()解分配返回的指针。失败时,返回空指针。
通过malloc()分配的空间是未初始化的空间;通常我们用memset()来对这块空间初始化
#include<stdlib.h>
#include<string.h>
#include<stdio.h>
int main(){
//用指针p指向这块内存
int *p=(int *)malloc(sizeof(int));
memset(p,0,sizeof(int));
printf("*p=%d",*p);
free(p);
return 0;
}
typedef struct node_s {
int val;
struct node_s* next;
} Node;
typedef struct link_s {
Node* head;
Node* tail;
int size;
} Linklist;
void add_before_head(Linklist* list, int val)
{
Node* newnode = (Node*)malloc(sizeof(Node));
if (newnode == NULL)
{
printf("add_before_head newnode is NULL");
exit(1);
}
else
{
newnode->val = val;
//newnode->next的节点是向NULL方向的节点
newnode->next = list->head;
list->head = newnode;
if(list->size==0)
list->tail = newnode;
list->size++;
}
}
在C语言中通常通过malloc来创建节点。
calloc()与malloc()的区别就是calloc()会将分配的内存初始化为零
typedef struct node_s {
int val;
struct node_s* next;
} Node;
typedef struct link_s {
Node* head;
Node* tail;
int size;
} Linklist;
Linklist* create_linklist()
{
return (Linklist*)calloc(1, sizeof(Linklist));
}
通过calloc创建一个空链表,将链表初始化头节点和尾节点都指向NULL。
通过realloc()对分配的内存空间进行再分配。可能之前分配的空间大了或者小了。我们可以通过realloc()对它再分配,因此他只能是对内存空间再分配,而不是用它新创建一块内存空间。因此ptr指针是指向之前开辟的堆区空间。
将开辟出的堆区空间进行释放,如果我们一直开辟空间而不去释放,就会导致内存泄漏。这对于一些程序是致命的,我们知道服务器是24小时不停工作的,如果服务器去一直开辟堆区空间而不去释放,慢慢的内存就会爆满导致服务器宕机。
C++中我们使用new和delete来进行堆空间的申请和释放
#include<iostream>
using namespace std;
int main() {
//开辟堆空间并赋初值为10
int* p = new int(10);
//在内存中开辟一个数组,其中后面的小括号代表赋初值的意思
int* parr = new int[10]();
cout << "*p=" << *p << endl;
//*parr是数组的第一个元素,因为小括号什么也没添默认是零
cout << "*parr=" << *parr << endl;
//释放指向int的内存
delete p;
//释放指向数组的内存
//这里释放数组内存比较特殊需要在前面加中括号
delete[] parr;
return 0;
}
需要注意的是对于释放数组的内存需要在前面加中括号。