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

Re:从零开始的 C++ 进阶篇(二)C++继承到底做了什么?从对象模型到底层内存布局彻底讲透

Re:从零开始的 C++ 进阶篇(二)C++继承到底做了什么?从对象模型到底层内存布局彻底讲透

◆ 博主名称: 晓此方-ZEEKLOG博客大家好,欢迎来到晓此方的博客。⭐️C++系列个人专栏: 主题曲:C++程序设计⭐️ 踏破千山志未空,拨开云雾见晴虹。 人生何必叹萧瑟,心在凌霄第一峰 0.1概要&序論 这里是此方,好久不见。 继承是 C++ 中最核心却最易被误解的机制之一。它不仅关乎语法层面的扩展,更涉及对象模型、内存布局与多态实现。本文将从底层原理出发,系统解析继承的真实运作机制。这里是「此方」。让我们现在开始吧! 一,初识继承 1.1 继承的概念与使用方法导入 继承(inheritance)机制是面向对象程序设计使代码可以复用的最重要的手段,它允许我们在 保持原有类特性的基础上进行扩展,增加方法(成员函数)和属性(成员变量),这样产生新的类,称为 派生类。 继承呈现了面向对象程序设计的层次结构,体现了由简单到复杂的认知过程。以前我们接触的函数层次的复用,继承是类设计层次的复用。

By Ne0inhk
C++从入门到实战(十一)详细讲解C/C++语言中内存分布与C与C++内存管理对比

C++从入门到实战(十一)详细讲解C/C++语言中内存分布与C与C++内存管理对比

C++从入门到实战(十一)详细讲解C/C++语言中内存分布与C与C++内存管理对比 * 前言 * 一、C/C++语言中内存分布 * 1.内核空间 * 2.栈 * 3.堆 * 4.数据段 * 5.代码段 * 二、例题带练巩固C/C++语言中内存分布的知识 * 题目讲解 * 题目答案 * 三、C语言动态内存分配(知识回顾) * 3.1 为什么需要动态内存分配 * 3.2 malloc 函数 * 3.3 calloc 函数 * 3.4 realloc 函数 * 3.5 free 函数

By Ne0inhk
C++入门看这一篇就够了——超详细讲解(120000多字详细讲解,涵盖C++大量知识)

C++入门看这一篇就够了——超详细讲解(120000多字详细讲解,涵盖C++大量知识)

目录 一、面向对象的思想 二、类的使用 1.类的构成 2.类的设计 三、对象的基本使用 四、类的构造函数 1.构造函数的作用 2.构造函数的特点 3.默认构造函数 3.1.合成的默认构造函数 3.2.手动定义的默认构造函数 四、自定义的重载构造函数 五、拷贝构造函数 1.手动定义的拷贝构造函数 2.合成的拷贝构造函数 3.什么时候调用拷贝构造函数 六、赋值构造函数 七、析构函数 八、this指针 九、类文件的分离 十、静态数据 1.静态数据成员 2.静态成员函数 十一、

By Ne0inhk
【C++:智能指针】没有垃圾回收?智能指针来也!破解C++内存泄漏:智能指针原理、循环引用与线程安全详解

【C++:智能指针】没有垃圾回收?智能指针来也!破解C++内存泄漏:智能指针原理、循环引用与线程安全详解

🎬 个人主页:艾莉丝努力练剑 ❄专栏传送门:《C语言》《数据结构与算法》《C/C++干货分享&学习过程记录》 《Linux操作系统编程详解》《笔试/面试常见算法:从基础到进阶》《Python干货分享》 ⭐️为天地立心,为生民立命,为往圣继绝学,为万世开太平 🎬 艾莉丝的简介: 🎬 艾莉丝的C++专栏简介: 文章目录 * C++学习阶段的三个参考文档 * 1 ~> 前言:智能指针的使用场景 * 2 ~> RAII和智能指针的设计思路 * 2.1 理论:RAII * 2.2 最佳实践 * 2.3 实践RAII:核心思想 * 3 ~> C++标准库智能指针的使用 * 3.1 理论

By Ne0inhk