栈是一种遵循后进先出原则的数据结构,C++标准库中的stack容器适配器的实现就基于这个特性,它封装了底层容器,只暴露符合栈操作规范的接口,非常适合需要后进先出逻辑的场景。

stack栈容器的基础说明
stack本身不是完整的容器,而是容器适配器,默认底层使用deque作为存储结构,也可以手动指定使用vector或者list作为底层容器。要使用stack需要引入对应的头文件,它的核心操作都围绕后进先出的特性设计。
引入头文件与声明栈对象
使用stack前需要包含<stack>头文件,声明栈对象时可以指定存储的元素类型和底层容器类型,不指定底层容器的话默认使用deque。
#include <stack>
#include <iostream>
#include <vector>
int main() {
// 默认底层使用deque的int类型栈
std::stack<int> int_stack;
// 指定底层使用vector的double类型栈
std::stack<double, std::vector<double>> double_stack;
return 0;
}
stack常用成员函数
stack提供的接口比较简洁,所有操作都符合栈的后进先出特性,常用的成员函数如下:
| 函数名 | 功能说明 |
|---|---|
| push(const T& val) | 将元素val压入栈顶 |
| pop() | 弹出栈顶元素,不返回该元素的值 |
| top() | 返回栈顶元素的引用,不会移除该元素 |
| empty() | 判断栈是否为空,为空返回true,否则返回false |
| size() | 返回栈中元素的个数 |
完整使用示例
下面通过一个完整的示例展示stack的入栈、出栈、获取栈顶元素、判断栈状态等操作的用法,直观体现后进先出的特性。
#include <stack>
#include <iostream>
int main() {
// 声明一个存储int类型的栈
std::stack<int> num_stack;
// 判断栈是否为空
if (num_stack.empty()) {
std::cout << "初始栈为空" << std::endl;
}
// 入栈操作,依次压入1、2、3
num_stack.push(1);
num_stack.push(2);
num_stack.push(3);
std::cout << "当前栈的元素个数:" << num_stack.size() << std::endl;
// 获取栈顶元素,此时栈顶是最后压入的3
std::cout << "当前栈顶元素:" << num_stack.top() << std::endl;
// 出栈操作,会先弹出3
num_stack.pop();
std::cout << "弹出栈顶元素后,新的栈顶元素:" << num_stack.top() << std::endl;
// 循环弹出所有元素,验证后进先出
std::cout << "依次弹出栈中所有元素:" << std::endl;
while (!num_stack.empty()) {
std::cout << num_stack.top() << " ";
num_stack.pop();
}
std::cout << std::endl;
return 0;
}
上述代码的输出结果如下:
初始栈为空 当前栈的元素个数:3 当前栈顶元素:3 弹出栈顶元素后,新的栈顶元素:2 依次弹出栈中所有元素: 2 1
使用注意事项
- 调用
top()函数前需要确保栈不为空,否则会引发未定义行为,建议先通过empty()判断栈状态。 pop()函数只负责弹出栈顶元素,不会返回该元素的值,如果需要获取弹出的元素,要先调用top()获取再调用pop()。- stack不支持遍历操作,也没有迭代器,只能通过
top()获取栈顶元素,不断弹出直到栈为空来获取所有元素。
常见应用场景
stack的后进先出特性适合很多场景,比如函数调用栈的实现、括号匹配校验、表达式求值、浏览器的页面前进后退逻辑等,掌握它的用法能帮助解决很多实际的开发问题。