1. 分配方式
- 栈:由编译器自动分配和释放,函数的参数、局部变量等都在栈上分配。例如,在函数内部定义一个变量
int a = 10;
,变量 a
就在栈上分配内存。
- 堆:需要程序员手动分配和释放,使用
new
(C++)或 malloc
(C 兼容)操作符进行分配,使用 delete
(C++)或 free
(C 兼容)操作符释放。例如,int* ptr = new int(10);
,通过 new
操作符在堆上分配了一个 int
类型的内存空间,并返回指向该空间的指针 ptr
。
2. 内存管理
- 栈:内存管理简单高效,随着函数的调用和返回,栈上的变量自动创建和销毁,不需要程序员手动干预,减少了内存泄漏的风险。
- 堆:程序员需要手动管理内存的释放,如果忘记调用
delete
或 free
,会导致内存泄漏。例如:
int* ptr = new int(10);
// 如果后续没有执行 delete ptr; 则会造成内存泄漏
3. 分配效率
- 栈:分配效率高,因为栈的操作类似于数据结构中的栈,遵循后进先出(LIFO)原则,内存分配和释放只需要移动栈指针,这是非常快速的操作。
- 堆:分配效率相对较低,堆内存的分配涉及到复杂的内存管理算法,如空闲链表法等,以找到合适的内存块,并且可能需要进行内存碎片整理等操作。
4. 实际代码中的示例
class MyClass {
public:
int data;
MyClass(int val) : data(val) {}
};
int main() {
// 堆分配一个 MyClass 对象
MyClass* obj = new MyClass(42);
// 使用完后需要手动释放
delete obj;
// 堆分配一个数组
int* arr = new int[10];
for (int i = 0; i < 10; ++i) {
arr[i] = i;
}
// 释放数组
delete[] arr;
return 0;
}
void func() {
int num = 5; // 栈分配一个 int 变量
int arr[10]; // 栈分配一个数组
for (int i = 0; i < 10; ++i) {
arr[i] = i;
}
// 函数结束时,num 和 arr 自动从栈上释放
}
int main() {
func();
return 0;
}