C++之stack类的代码及其逻辑详解

C++之stack类的代码及其逻辑详解

1. stack介绍及使用方法

stack是一种后进先出的数据结构,所以在C++的STL库中也同样遵循了这一点,我们在使用的时候

不支持随机访问或迭代器遍历。

注意事项
  • 调用 top() 或 pop() 前需确保栈非空,否则可能引发未定义行为。
  • stack 没有 clear() 函数,如需清空栈需手动循环调用 pop()
  • 性能:所有操作的时间复杂度为 O(1)。

stack的底层是一个 deque<T>(双端队列),虽然deque是可以从两端来进行操作的,但是我们只要只提供一端的接口,那么就可以来把它当做stack来使用。

我们在空间上要把它理解成这个样子,瘟疫这样更好理解。

2. stack的常用接口

函数名作用
void push(const T& x)放一个元素进入stack
void pop()抛出一个元素
T& top()返回最后一个放入的元素
size_t size()返回stack里面的元素个数
bool empty()判断是否为空

接下来我会一一实现这些端口。

3. template

在这里写两个calss是为了方便使用,这两个模板参数实际上是各司其职,只是语法上要求写在同一个 template<> 里,使用时会根据场景自动匹配对应的参数。

前面的 T 是明确指定栈中元素的类型(比如 intstring 等),这是栈对外提供的 “数据类型契约”—— 栈里只能存 T 类型的东西。后面的 Container 是指定用什么容器来存储这些 T 类型的元素,而默认的 deque<T> 就是 “用双端队列来存 T 类型元素” 的意思。

PS:只写后面那一个理论上来说也是可以的,但是会让用户使用门槛变高,比如想声明一个存 int 的栈,用户不能直接写 stack<int>,而必须写成 stack<deque<int>>(如果想用默认容器),或者 stack<vector<int>>。这会让接口变得不直观 —— 用户需要先知道底层容器的类型,才能正确声明栈,违背了 “栈是容器适配器,用户无需关心底层实现” 的设计初衷。

PS:只写前面哪一个是不行的,如果只写 template<class T>,就意味着用户无法指定底层容器了 —— 因为没有 Container 这个参数来接收用户自定义的容器类型。

template<class T, class Container = deque<T>>

4. private

这就是申明一个私有成员_con。

private: Container _con;

5.pop()

抛出最后一个元素(因为是后进先出)。

void pop() { _con.pop_back(); }

6. top()

返回最后一个元素(不抛出)。

T& top() { return _con.back(); }

7. size()

返回stack里面元素的个数。

size_t size() { return _con.size(); }

8.empty

判断是否为空,为空的话就返回true。

bool empty() { return _con.empty(); }

9. push()

在尾部的位置上插入一个元素。

void push(const T& x) { _con.push_back(x); }

10. 总结

stack到这边就讲完了,作为 C++ 中常用的容器适配器,以简洁的接口和灵活的底层设计,为 LIFO 场景提供了高效支持。理解其底层依赖deque的原因、掌握核心接口的使用规范,能帮助开发者在实际场景中更合理地选择和使用stack,避免因误用接口导致的逻辑错误。

以下是完整代码:

#pragma once #include<vector> #include<deque> namespace struggle { // template<class T, class Container = deque<T>> class stack { public: void push(const T& x) { _con.push_back(x); } void pop() { _con.pop_back(); } T& top() { return _con.back(); } size_t size() { return _con.size(); } bool empty() { return _con.empty(); } private: Container _con; }; 

Read more

【算法竞赛】C/C++ 的输入输出你真的玩会了吗?

【算法竞赛】C/C++ 的输入输出你真的玩会了吗?

🔭 个人主页:散峰而望 《C语言:从基础到进阶》《编程工具的下载和使用》《C语言刷题》《算法竞赛从入门到获奖》《人工智能AI学习》《AI Agent》 愿为出海月,不做归山云 🎬博主简介 文章目录 * 前言 * 1. OJ(online judge)题目输入情况汇总 * 1.1 单组测试用例 * 1.2 多组测试用例 * 1.2.1 测试数据组数已知 * 1.2.2 测试数据组未知 * 1.2.3 特殊值结束测试数据 * 2. 输入时特殊技巧 * 2.1 含空格字符串的特殊处理方式 * 2.2 数字的特殊处理方式 * 3. scanf/printf 和

By Ne0inhk
C++ 波澜壮阔 40 年:引用、内联函数与现代空指针,效率跃升三基石

C++ 波澜壮阔 40 年:引用、内联函数与现代空指针,效率跃升三基石

🔥@晨非辰Tong: 个人主页 👀专栏:《数据结构与算法入门指南》、《C++学习之旅》 💪学习阶段:C语言、数据结构与算法初学者 ⏳“人理解迭代,神理解递归。” 文章目录 * 引言 * 一、引用:C++前期重难点 * 1.1 一览:引用的方方面面 * 1.2 划重点:引用的正确使用 * 1.3 存疑的地方 * 1.4 const引用 * 1.5 引用和指针的关系(面试必看) * 二、inline内联函数 * 2.1 对要点的详细解释 * 三、宏:nullptr * 总结 引言 C++的演进之路,是不断在性能与安全、灵活与严谨之间寻求平衡的艺术。 本文将深入剖析三大特性:

By Ne0inhk
RPC魔法揭秘:从原理到BRPC实战,用C++玩转分布式通信

RPC魔法揭秘:从原理到BRPC实战,用C++玩转分布式通信

文章目录 * 本篇摘要 * 一.什么是rpc * 简单理解 * 核心特点 * RPC 工作原理 * 常见 RPC 框架 * 典型使用场景 * 二.BRPC介绍 * 是什么? * 比gRPC强在哪? * 三.基于brpc实现简单的服务调用 * brpc安装教程 * 简单实现客户端向brpc服务端口请求服务完成应答过程(以echo回显为例) * 测试效果 * 代码汇总 * 四.封装每个服务的channels及所有服务管理者 * 五.基于etcd实现服务上下线监控来完成brpc服务调用 * 测试效果 * 代码汇总 * 六.本篇小结 本篇摘要 本文从RPC核心概念出发,阐释其“透明远程调用”的本质与工作原理,对比主流框架后聚焦百度开源的C++高性能RPC框架BRPC,详解其安装、Echo服务示例代码(含客户端/服务端实现),并延伸介绍基于ETCD的服务注册发现与信道管理封装,完整呈现分布式通信方案落地过程。 一.什么是rpc 简单理解 RPC(远程过程调用)就是让程序调用

By Ne0inhk
C++的IO流和C++的类型转换----《Hello C++ Wrold!》(29)--(C/C++)

C++的IO流和C++的类型转换----《Hello C++ Wrold!》(29)--(C/C++)

文章目录 * 前言 * C++的类型转换 * 四种命名的强制类型转换操作符 * static_cast * reinterpret_cast * const_cast * dynamic_cast * RTTI(这个了解一下就行了) * C++的IO流 * C++文件的IO流 * stringstream 前言 在 C++ 编程体系中,类型转换与 IO 流是支撑程序数据处理与交互的两大核心环节。类型转换关乎数据在不同类型间的安全传递与运算适配,而 IO 流则负责程序与外部设备(如键盘、屏幕、文件)之间的数据输入与输出,二者共同构成了 C++ 程序实现功能、交互信息的基础框架。 C 语言中的类型转换方式虽简洁,却存在可视性差、难以追踪的问题,容易在复杂程序中引发潜在的逻辑错误。为解决这一痛点,C++ 引入了四种命名明确的强制类型转换操作符 ——static_cast、reinterpret_

By Ne0inhk