栈和堆简介
栈(Stack) 特点:
- 先进后出(
LIFO
,Last In First Out
):栈遵循后进先出
原则,意味着最后压入栈的数据最先弹出。 - 内存分配:栈由操作系统
自动管理
,内存分配和释放非常迅速。 - 生命周期:栈内存通常在函数调用时
自动分配
,函数执行完后自动释放
。 - 大小限制:栈的大小相对
较小
,由系统规定,容易发生栈溢出(stack overflow)。
用途:
- 局部变量:在函数中定义的
局部变量
通常分配在栈上。 - 函数调用管理:栈用于存储函数的
调用信息
,包括参数
、返回地址
、局部变量
等。
堆(Heap) 特点:
- 先进先出(
FIFO
,First In First Out
):堆是一个相对较大、灵活的内存区域,内存分配和释放由程序员控制
,动态
分配,分配顺序不固定
。 - 内存分配:堆内存分配和释放较为复杂,需要程序员
手动管理
(例如 C/C++ 中使用malloc
和free
)。 - 生命周期:堆内存分配后
不会自动释放
,除非程序显式释放
。否则,可能发生内存泄漏。 - 大小限制:堆的大小通常
较大
,只受限于系统的物理内存。
用途:
- 动态内存分配:堆用于存储需要
动态分配
和长时间存在
的数据,如动态数组
、链表
、树
等。 长时间存活
的数据:例如,当数据需要在多个函数之间共享时,通常会存放在堆上。
模板类的示例-栈
模板类
最常用的就是作为容器类
。C++标准库:栈、数组、链表、二叉树和哈希表,都是用模板类实现的。
进栈出栈
示例代码:
#include <iostream>
using namespace std;
class Stack // 小写的stack是C++标准库的栈,为了避免重复,此处使用大写的Stack
{
public:
int* items; // 栈数组
int stacksize; // 栈大小
int top; // 栈顶指针
public:
Stack(int size):stacksize(size), top(0) {
// top(0) 表示栈顶指针初始化为0,即栈为空。
items = new int[stacksize]; // 分配栈数组内存
}
~Stack() {
delete [] items; items = nullptr;
}
bool isEmpty() {
// 判断栈是否为空
return top == 0;
}
bool isFull() {
// 判断栈是否已满
return top == stacksize;
}
bool push(const int& item) {
// 入栈操作
// 如果栈未满,则可入栈
if(top < stacksize) {
items[top++] = item; return true;}
// top++ 的意义:先使用 top 的当前值,然后将其递增,确保栈顶索引始终指向下一个可用位置。
return false;
}
bool