首页 / 第十一章 · STL 标准模板库 / 11.5 stack

11.5 stack 栈

后进先出(LIFO)的容器适配器——只能在栈顶操作,像一摞盘子,只能从最上面放、从最上面取。

本页目录

stack 是一种后进先出(LIFO,Last In First Out)的容器适配器。它底层默认使用 deque 实现,只开放有限的接口,只允许在栈顶进行插入和删除操作。形象地理解,它就像一摞盘子——你只能放新的在最上面,也只能从最上面取走。使用前需引入 <stack> 头文件。

1
2
3
栈顶在最上面 ↑
s.top() = 3
push(x) 放在最上面
pop() 从最上面拿走
· 只能操作栈顶,碰不到下面
⚠️
注意:
· stack容器适配器,不是独立容器,它底层默认用 deque 实现,只开放有限的接口。不能用迭代器遍历它
· 对空栈调用 top()pop() 是未定义行为,使用前务必用 empty() 检查。
11.5.1 定义与初始化
C++ · stack 的定义方式
1#include <iostream>
2#include <stack> // 必须包含这个头文件
3using namespace std;
4
5int main()
6{
7 stack<int> s1; // 空栈
8 stack<int> s2(s1); // 拷贝另一个栈
9 return 0;
10}
11.5.2 常用操作
C++ · push / top / pop
1stack<int> s;
2// 压入元素
3s.push(1); // 栈:[1]
4s.push(2); // 栈:[1, 2]
5s.push(3); // 栈:[1, 2, 3]
6
7// 查看栈顶
8cout << s.top() << endl; // 输出:3(栈顶元素)
9
10// 弹出栈顶
11s.pop(); // 弹出 3,栈变成 [1, 2]
12
13// 容量
14cout << s.size() << endl; // 输出:2
15cout << s.empty() << endl; // 输出:0(false,不空)
16
17// 交换
18s1.swap(s2); // 交换两个栈的全部内容
19s.emplace(10); // 在栈顶原地构造元素(比 push 更高效)
11.5.3 🔥 经典陷阱

陷阱一:pop() 不返回被删除的值!

C++ · pop() 的常见误用
1stack<int> s;
2s.push(10);
3
4// ❌ 错误写法——pop() 返回 void,不能赋值
5int x = s.pop(); // 编译错误!
6
7// ✅ 正确写法——先取栈顶,再弹出
8int x = s.top(); // 先拿到 10
9s.pop(); // 再把 10 弹出
🔥
为什么会这样?pop() 的设计哲学是"删除"和"读取"分开:pop() 只负责删除,返回类型是 void;要读取栈顶的值,必须先调用 top()。这和很多人直觉里"弹出并返回"的想法不一样,是 STL 容器适配器里最容易踩的坑之一。

陷阱二:空栈调用 top() 或 pop() 是危险操作

C++ · 操作前先检查 empty()
1stack<int> s; // 空栈
2
3// ❌ 危险!程序可能直接崩溃
4cout << s.top();
5s.pop();
6
7// ✅ 安全做法——操作前先检查
8if (!s.empty())
9{
10 cout << s.top();
11 s.pop();
12}
11.5.4 完整使用示例
C++ · stack 综合示例
1#include <iostream>
2#include <stack>
3using namespace std;
4
5int main()
6{
7 stack<int> s;
8
9 // 压入三个元素
10 s.push(1);
11 s.push(2);
12 s.push(3);
13
14 cout << "栈顶: " << s.top() << endl; // 输出:3
15 cout << "大小: " << s.size() << endl; // 输出:3
16
17 // 逐个弹出(后进先出)
18 cout << "依次弹出: ";
19 while (!s.empty())
20 {
21 cout << s.top() << " "; // 输出:3 2 1
22 s.pop();
23 }
24 cout << endl;
25
26 cout << "是否为空: " << s.empty() << endl; // 输出:1(true)
27
28 return 0;
29}
📋 stack 常用操作速查表

把本节出现过的方法按用途归类汇总,写代码时可以直接当参考卡用。

方法分类作用
s.push(x)修改压入元素到栈顶
s.pop()修改弹出栈顶元素,不返回值
s.emplace(args...)修改在栈顶原地构造元素,省去拷贝
s.top()访问读取(不删除)栈顶元素
s.size() / s.empty()容量元素个数 / 判断是否为空
s1.swap(s2)修改交换两个栈的全部内容
🎯
什么时候用 stack?括号匹配、表达式求值、DFS(深度优先搜索)的非递归实现、撤销操作(undo)……任何"最近发生的事先处理"的场景都是 stack 的舞台。