c++中如何使用stack栈容器_c++后进先出数据结构【入门】

5次阅读

std::stack 默认底层容器是 std::deque 而非 std::vector,支持两端高效操作但不支持随机访问;top() 返回顶引用,pop() 为 void 函数;判空应优先用 empty();auto 声明无法访问底层容器。

c++中如何使用stack栈容器_c++后进先出数据结构【入门】

std::stack 默认用 deque 实现,不是 vector

很多人以为 std::stack 底层默认是 std::vector,其实不是——它默认用的是 std::deque。这直接影响性能和内存行为:deque 支持两端高效插入删除,而 vector 只在尾部快;如果频繁调用 push()pop(),deque 更稳,但随机访问(比如想“看第 3 个元素”)完全不支持——std::stack 根本没提供下标操作。

实操建议:

  • 别试图用 stack[i]stack.at(i) —— 编译直接报错:no operator[]
  • 真需要随机访问或遍历,请改用 std::vectorstd::deque 手动模拟逻辑
  • 若明确要连续内存、且确定不会中途扩容太多,可显式指定底层容器:std::stack<int std::vector>> s;</int>

top() 返回引用,但 pop() 不返回任何值

top() 返回的是栈顶元素的引用(T&const T&),而 pop() 是个 void 函数——它只删不返。这是初学者最常踩的坑:写成 int x = s.pop(); 会编译失败,错误信息是:void value not ignored as it ought to be

正确做法永远是两步:

立即学习C++免费学习笔记(深入)”;

  • 先用 top() 拿值
  • 再用 pop() 删掉
  • 注意:如果栈为空就调 top()pop(),行为未定义(通常 crash 或读垃圾值)

示例:

if (!s.empty()) {     int x = s.top();     s.pop();     // 处理 x }

empty() 比 size() == 0 更安全、更高效

判断栈是否为空,优先用 empty(),而不是 size() == 0。原因有两个:一是某些容器(虽然 deque/vector 都是 O(1))理论上 size() 可能非 O(1),二是语义更清晰——你关心的是“有没有”,不是“有多少”。

更重要的是习惯问题:一旦换到其他标准容器(比如 std::list 在旧标准里 size() 是 O(n)),size() == 0 就成了性能雷区。

常见错误场景:

  • 循环中反复写 while (s.size() > 0) —— 改成 while (!s.empty())
  • s.size() 当作可索引依据(比如想“取倒数第二个”)——std::stack 不支持

不能用 auto 推导 stack 的底层容器类型

声明时如果写 auto s = std::stack<int>();</int>,推导出的类型是 std::stack<int></int>,但你想访问底层容器(比如调试时想打印所有元素),就卡住了——std::stackc 成员设为 private,不提供公开接口暴露它。

所以,除非你只做标准栈操作(push/top/pop/empty/size),否则别依赖 auto 声明。需要底层访问时,老老实实用具体类型:

  • 想看内部 deque:std::stack<int std::deque>> s;</int>,然后通过继承或友元绕过封装(不推荐)
  • 更实际的做法:直接用 std::deque<int></int>,自己控制 push_back() / pop_back()
  • 调试时临时复制:用循环 + top/pop 把所有元素倒进 vector 再打印

真正难的从来不是“怎么压栈”,而是“栈空了还继续 top”或者“以为能遍历结果运行时报错”。这些地方没运行时检查,错了就是静默 UB。

text=ZqhQzanResources