std::stack默认底层容器是std::deque而非std::vector;可显式指定vector以获得连续内存;需注意拷贝/移动语义、析构调用、无迭代器、优先用empty()判空及异常安全。
std::stack 最快实现,但得知道它默认用什么容器std::stack 不是独立容器,而是适配器——它底层默认用 std::deque,不是 std::vector。这点容易被忽略,导致性能误判。比如频繁扩容时,deque 的分段内存比 vector 更少触发整体拷贝,但随机访问慢;如果明确要连续内存和可控增长策略,可以显式指定:
std::stack<int, std::vector<int>> s;这样构造后,
s 就基于 vector,push() 可能触发重分配,但 top() 和 pop() 仍是 O(1)。自己实现栈类时,若模板参数类型是 std::string 或自定义类,必须正确处理构造、析构和赋值。常见错误是浅拷贝内部数组指针,或忘记在 pop() 后调用元素析构函数。C++11 起推荐用 std::unique_ptr<T[]> 管理内存,并在 push() 时用 new (ptr + size) T(std::move(value)) 定位构造,在 pop() 时显式调用 ptr[size-1].~T()。不这么做,std::string 类型的栈可能泄漏内存或重复析构。
std::stack 没有迭代器,遍历栈必须靠临时容器中转标准库故意不提供 begin()/end(),因为这违背栈的 LIFO 抽象。真要打印全部内容或调试检查,不能直接 for-each。可行做法是:把栈元素逐个 pop() 到 std::vector,再反向遍历(或用另一个栈暂存):
std::vector<int> tmp;<br>while (!s.empty()) {<br> tmp.push_back(s.top());<br> s.pop();<br>}<br>// 此时 tmp 是逆序,可正向遍历注意:这个操作会清空原栈。如需保留,得先拷贝一份——而 std::stack 不支持拷贝构造(除非底层容器支持),所以更稳妥的是从头重建。std::stack 时别依赖 size() == 0 判断空,优先用 empty()
empty() 是常量时间,size() 对某些底层容器(比如基于 list 的自定义适配器)可能是 O(n)。虽然 std::deque 和 std::vector 的 size() 都是 O(1),但标准没保证所有适配器都如此。实际写法应统一用:
if (s.empty()) { /* ... */ }而不是 if (s.size() == 0)。另外,对空栈调用 top() 或 pop() 是未定义行为,务必先判空。立即学习“C++免费学习笔记(深入)”;
手写栈真正麻烦的不是 push/pop 逻辑,而是异常安全——比如 push() 中内存分配失败时,原有栈状态是否完整。标准库的 std::stack 把这部分压力转移给了底层容器,自己用的时候得心里有数。