引言
在c语言中我们开辟数组都是指定空间
int arr[10]={0};//在栈空间上开辟四十个字节
char arry[10]={0};//在栈空间上开辟十个字节
这种开辟空间的缺点:
- 空间开辟大小是固定的
- 数组在申明的时候,必须指定数组的长度,它所需要的内存在编译时分配
但我们时常不知道空间具体要开多大,只有程序运行的时候才能知道,这时数组编译时开辟空间就不满足,所以这种时候往往需要动态开辟内存来解决
C/C++内存分布

代码段
-
存储内容:程序的可执行指令
-
特性:只读、在程序运行期间不变
-
包含:机器指令、字符串常量
-
示例:函数定义、
"hello world"字符串
数据段
-
存储内容:已初始化的全局变量和静态变量
-
特性:在程序开始时就分配,生命周期与程序相同
-
包含:
-
全局变量(初始化)
-
静态变量(初始化)
-
常量(部分)
-
int global_var = 100; // 数据段
static int static_var = 200; // 数据段
BSS 段
-
存储内容:未初始化的全局变量和静态变量
-
特性:在程序开始时自动初始化为0
-
包含:
-
未初始化全局变量
-
未初始化静态变量
-
int uninit_global; // BSS段
static int uninit_static; // BSS段
堆 (Heap)
-
存储内容:动态分配的内存
-
特性:手动管理(malloc/free, new/delete),向上增长
-
生命周期:由程序员控制
int *arr = (int*)malloc(100 * sizeof(int)); // 堆内存
栈 (Stack)
-
存储内容:局部变量、函数参数、返回地址
-
特性:自动管理,向下增长,LIFO(后进先出)
-
生命周期:函数调用期间
-
void function() { int local_var = 10; // 栈内存 char buffer[100]; // 栈内存 }内存特性对比
区域 存储内容 管理方式 增长方向 生命周期 代码段 程序指令 系统 固定 程序运行期 数据段 初始化全局/静态变量 系统 固定 程序运行期 BSS段 未初始化全局/静态变量 系统 固定 程序运行期 堆 动态分配内存 手动 向上 程序员控制 栈 局部变量、函数参数 自动 向下 函数调用期
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int data_var = 100; // 数据段
int bss_var; // BSS段
const char* str = "Hello"; // 代码段(字符串在代码段)
void function(int param) { // 代码段
int local_var = 10; // 栈
static int static_local = 5; // 数据段
char* heap_mem = (char*)malloc(100); // 堆
strcpy(heap_mem, "Dynamic");
free(heap_mem); // 需要手动释放
}
int main() { // 代码段
function(20); // 参数在栈
return 0;
}
C语言动态内存管理方式
malloc

malloc函数向内存申请一块连续可用的空间,并返回指向这块空间的指针
malloc特性
- 开辟成功,则返回一个指向开辟好空间的指针
- 开辟失败,则返回一个NULL指针
- 返回值的类型是 void*,malloc函数不知道需要开辟什么空间的类型,需要由自己设置
- 如果参数 size 为0,malloc的行为是标准是未定义的,取决于编译器
- 分配的内存块的内容不会初始化,保留不确定值
- 此函数从不抛出异常
malloc用法
int* a=(int*)malloc(sizeof(int));
int* a=(int*)malloc(int);
realloc

realloc函数相较与malloc函数,动态内存管理更加灵活
realloc特性
- 重新分配内存块
- 该函数可以将内存块移动到新位置(其地址由函数返回)
- 如果是空指针,则该函数的行为类似于 ,分配一个新的字节块并返回指向其开头的指针
realloc用法
int* a=(int*)malloc(sizeof(int));
int* b=(int*)realloc(a,sizeof(int)*10);
- 原有空间之后有足够大的空间
要扩展内存就直接原有内存之后直接追加空间,原来空间的数据不发生变化
- 原有空间之后没有足够大的空间
原有空间之后没有足够多的空间时,扩展的方法是:在堆空间上另找一个合适大小的连续空间来使用,这样函数返回的是一个新的内存地址
calloc
函数的功能是为 num 个大小为 size 的元素开辟一块空间,并且把空间的每个字节初始化为0与函数 malloc 的区别只在于 calloc 会在返回地址之前把申请的空间的每个字节初始化为全0
calloc用法
int *p = (int*)calloc(10, sizeof(int));

当对申请的内存空间内容要求初始化时,可以用calloc函数
free

free函数用来释放动态开辟的内存
free特性
- 参数 ptr 指向的空间不是动态开辟的,那free函数的行为是未定义的
- 如果参数 ptr 是NULL指针,则函数什么事都不做
free用法
#include <stdlib.h> /* malloc, calloc, realloc, free */
int main ()
{
int * buffer1, * buffer2, * buffer3;
buffer1 = (int*) malloc (100*sizeof(int));
buffer2 = (int*) calloc (100,sizeof(int));
buffer3 = (int*) realloc (buffer2,500*sizeof(int));
free (buffer1);
free (buffer3);
return 0;
}
malloc/calloc/realloc三者区别
| 特性 | malloc | calloc | realloc |
|---|---|---|---|
| 初始化 | 不初始化 | 初始化为0 | 保持原内容 |
| 参数 | 总字节数 | 元素个数 × 元素大小 | 指针 + 新大小 |
| 用途 | 一般分配 | 需要零初始化的分配 | 调整已分配内存大小 |
| 性能 | 较快 | 稍慢(因为要清零) | 取决于调整情况 |
使用注意事项
- 使用后必须用
free()释放内存 - 检查返回值是否为 NULL(分配失败)
realloc传入 NULL 指针时相当于mallocrealloc传入大小为 0 时相当于free
C++动态内存管理
new和delete
new开辟一个内存并初始化,delete释放旧内存
void Test()
{
// 动态申请一个int类型的空间
int* ptr4 = new int;
// 动态申请一个int类型的空间并初始化为10
int* ptr5 = new int(10);
// 动态申请10个int类型的空间
int* ptr6 = new int[10];
delete ptr4;
delete ptr5;
delete[] ptr6;
}

注意:申请和释放单个元素的空间,使用new和delete操作符,申请和释放连续的空间,使用 new[]和delete[],匹配起来使用
class A
{
public:
A(int a=1)
:_a(a)
{
cout<<"A()"<<this<<endl;
}
~A()
{
cout<<"~A()"<<this<<endl;
}
private:
int _a;
}:
int main()
{
A* aa1=new A(1);
delete aa1;
A* aa2=(A*)malloc(sizeof(A));
free(aa2);
A* aa3=new A[10];
delete[] aa3;
A* aa4=(A*)malloc(sizeof(A)*10);
free(aa4);
return 0;
}
malloc没办法支持动态申请空间的自定义对象初始化
在申请自定义类型的空间时,new会调用构造函数,delete会调用析构函数,而malloc与free不会
如果申请的是内置类型的空间,new和malloc,delete和free基本类似不同的地方是: new/delete申请和释放的是单个元素的空间,new[]和delete[]申请的是连续空间,而且new在申请空间失败时会抛异常,malloc会返回NULL
new的原理
- 调用operator new函数申请空间
- 在申请的空间上执行构造函数,完成对象的构造
delete的原理
- 在空间上执行析构函数,完成对象中资源的清理工作
- 调用operator delete函数释放对象的空间
new T[N]的原理
- 调用operator new[]函数,在operator new[]中实际调用operator new函数完成N个对象空间的申请
- 在申请的空间上执行N次构造函数
delete[]的原理
- 在释放的对象空间上执行N次析构函数,完成N个对象中资源的清理
- 调用operator delete[]释放空间,实际在operator delete[]中调用operator delete来释放空间
malloc/free和new/delete的区别
基本区别
| 特性 | malloc/free | new/delete |
|---|---|---|
| 语言 | C 语言库函数 | C++ 运算符 |
| 返回值 | void* (需要强制转换) | 正确类型的指针 |
| 参数 | 字节数 | 类型 |
| 初始化 | 不调用构造函数 | 调用构造函数 |
| 清理 | 不调用析构函数 | 调用析构函数 |
| 重载 | 不可重载 | 可以重载 |
| 异常 | 返回 NULL | 抛出 std::bad_alloc |
| 大小计算 | 手动计算 | 自动计算 |
总结
-
在 C++ 中优先使用 new/delete,因为它们支持面向对象特性
-
malloc/free 在 C 中使用,或在需要与 C 代码交互时使用
-
不要混用:用 new 分配的内存要用 delete 释放,用 malloc 分配的内存要用 free 释放

1万+

被折叠的 条评论
为什么被折叠?



