1. 内存分配区别
- 栈内存分配:由编译器自动管理,分配和释放速度快。当函数调用时,其局部变量(包括基本类型和对象)会在栈上自动分配空间。分配方式类似数据结构中的栈,按照后进先出(LIFO)的顺序。例如,在函数内定义一个
int a;
,a
就被分配在栈上。
- 堆内存分配:需要程序员手动申请和释放,通过
new
(C++ 中)等操作符来分配内存。堆内存的分配相对灵活,但速度较慢。它的分配空间大小不固定,可根据需求动态分配。例如,int* p = new int;
,通过new
操作符在堆上分配了一个int
类型大小的内存空间,并返回指向该空间的指针p
。
2. 释放机制区别
- 栈内存释放:当函数执行完毕,栈上的局部变量会自动被释放,无需程序员手动干预。例如函数结束时,函数内定义的栈变量空间自动回收。
- 堆内存释放:必须由程序员手动调用
delete
(C++ 中)操作符来释放,否则会导致内存泄漏。例如,前面在堆上分配的int
空间,需要delete p;
来释放。如果忘记释放,这块内存就一直占用,无法被其他程序使用。
3. 利用堆和栈存储数据实现动态数组
栈实现动态数组(使用数组对象,本质仍是栈上分配)
#include <iostream>
#include <array>
const int size = 5;
int main() {
std::array<int, size> stackArray;
for (int i = 0; i < size; i++) {
stackArray[i] = i;
}
for (int i = 0; i < size; i++) {
std::cout << stackArray[i] << " ";
}
return 0;
}
- 优点:
- 内存分配和释放自动管理,无需手动干预,代码简单,不容易出现内存泄漏。
- 访问速度快,因为在栈上分配,局部性原理使得数据访问效率高。
- 缺点:
- 数组大小在编译时就必须确定,缺乏灵活性,不能在运行时动态改变大小。
堆实现动态数组(使用new
分配数组)
#include <iostream>
int main() {
int size = 5;
int* heapArray = new int[size];
for (int i = 0; i < size; i++) {
heapArray[i] = i;
}
for (int i = 0; i < size; i++) {
std::cout << heapArray[i] << " ";
}
delete[] heapArray;
return 0;
}
- 优点:
- 可以在运行时动态分配内存大小,非常灵活,适合需要根据程序运行情况动态调整数据量的场景。
- 缺点:
- 需要手动管理内存释放,容易因忘记
delete
操作导致内存泄漏。
- 分配和释放内存的操作相对复杂,且堆内存分配速度较慢,会影响程序性能。