std::stack 默认用 std::deque 实现而非 vector,因其需两端高效操作;若需连续内存须显式指定 vector 为底层容器。

std::stack 默认用 deque 实现,不是 vector
很多人以为 std::stack 底层默认是 std::vector,其实标准规定它默认使用 std::deque。这会影响性能和内存布局:deque 支持两端高效插入/删除,而 vector 只保证尾端 O(1);但 deque 的元素不连续,遍历时缓存友好性差。
如果明确需要连续内存(比如要取栈底地址、或配合某些 SIMD 操作),得显式指定容器:
std::stack<int std::vector>> s;</int>
注意模板第二个参数是容器类型,不是实例。
push/emplace/pop 三者行为差异必须分清
push 接收一个已构造的对象,会触发拷贝或移动;emplace 在栈顶原地构造对象,避免中间临时对象;pop 只删不返值——这是最容易出错的地方:没有 top_and_pop 这样的原子操作。
- 想安全取栈顶并弹出,必须两步:
s.top()然后s.pop(),且顺序不能反 - 如果栈为空时调用
top()或pop(),行为未定义(不会抛异常,通常 crash) - 对自定义类型,
emplace能转发参数,比如s.emplace(1, "hello")会调用T(1, "hello")
empty() 和 size() 的性能在不同底层容器下不一样
empty() 在所有标准容器适配器中都是 O(1),放心用;但 size() 不一定——std::deque::size() 是 O(1),而某些老编译器的 std::list::size()(若你误传了 list)可能是 O(n)。虽然 stack 不允许直接传 list(因为 list 缺少 back()),但自定义容器时容易踩坑。
更关键的是:不要用 while (!s.empty()) 配合 s.size() 做循环条件,比如:
while (s.size() > 0) { ... }
这多了一次函数调用开销,且语义不如 empty() 清晰。标准库实现里 empty() 通常就是 size() == 0,但可内联优化,且意图明确。
不能用迭代器遍历 std::stack
std::stack 是容器适配器,故意不提供 begin()/end(),也不暴露底层容器。这是设计使然:它只承诺 LIFO 接口,不保证内部顺序或可遍历性。
如果你需要遍历(比如调试打印、查找某个值),有且仅有两个办法:
- 把元素一个个
pop出来,存到临时容器里再处理(注意原栈被清空) - 换用
std::vector或std::deque手动模拟栈行为,自己维护push_back/pop_back/back
强行通过 friend 或 reinterpret_cast 访问底层容器属于未定义行为,别试。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











