std::stack需指定元素类型,默认底层为deque,不支持列表初始化;常用操作为push、top(非空时调用)、pop(不返回值);无迭代器、无clear、无swap成员函数,线程不安全。

怎么声明和初始化一个 std::stack
直接用 std::stack 模板,必须指定元素类型,它默认底层容器是 std::deque,不支持直接传入初始元素列表(比如不能像 vector 那样用 {1,2,3} 初始化)。
常见写法:
std::stack<int> s; // 空栈 std::stack<std::string> words; // 存字符串 std::stack<int, std::vector<int>> s_vec; // 指定底层为 vector(注意:vector 不支持 pop_back 后再访问 back(),但 stack 封装后没问题)
注意:std::stack 是容器适配器,不是容器本身,所以没有迭代器,也不能用 for(auto x : s) 遍历。
push、top、pop 三个操作的顺序和陷阱
这是最常出错的一组操作——top() 返回的是引用,但调用前必须确保栈非空;pop() 不返回值,只删顶元素;误把 pop() 当作“取并删”会丢数据。
立即学习“C++免费学习笔记(深入)”;
-
s.push(x):插入到栈顶,时间复杂度 O(1) -
s.top():访问栈顶元素(不删除),若栈为空,行为未定义(通常崩溃或随机值) -
s.pop():删除栈顶元素,不返回任何值,不能写成int x = s.pop();
安全写法示例:
if (!s.empty()) {
int x = s.top(); // 先取值
s.pop(); // 再删除
}判断是否为空、获取大小:用 empty() 和 size()
empty() 是首选,比 size() == 0 更高效(某些实现下 size() 可能遍历计数,虽然标准要求 O(1),但习惯上仍优先用 empty())。
-
s.empty()→bool,推荐用于条件判断 -
s.size()→size_t,注意别和负数比较(比如s.size() - 1 永远为假,因为 <code>size_t是无符号) - 没有
clear()成员函数,清空只能循环pop(),或用作用域控制生命周期(更推荐)
实际场景中容易被忽略的点:拷贝、移动和线程安全
std::stack 支持拷贝构造和赋值(只要其底层容器和元素类型支持),但开销可能大(尤其是栈很深时);C++11 起也支持移动语义,传参建议用右值引用或 const 引用。
- 不要在多线程中无保护地共用同一个
std::stack实例——它**不保证线程安全**,push/top/pop都需外部加锁 - 没有
swap()成员函数,但有非成员std::swap(s1, s2),效率高(交换内部容器) - 如果需要遍历或随机访问,
stack不是合适选择——换用vector或deque,自己维护栈顶索引
真正用好 std::stack 的关键是:明确它只提供 LIFO 接口,其余一切需求(如查看中间元素、迭代、并发访问)都得绕开它处理。











