news 2026/6/10 12:48:30

[c++]deque容器详解

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
[c++]deque容器详解

求一个关注不过分吧?(看在文章这么精品的份上)


1. 概述

  • deque(双端队列,double-ended queue)是序列容器,支持在头尾两端高效地插入和删除元素。

  • 元素在内存中不是连续存储(与vector不同),但依然支持随机访问(通过下标或at())。

  • 位于<deque>头文件,命名空间std

cpp

#include <deque> using namespace std;

核心特点

  • 头尾插入/删除O(1)(摊销常数时间)。

  • 中间插入/删除O(n)(需要移动元素)。

  • 支持随机访问(下标[]at()),常数时间 O(1)。

  • 内存布局:通常由一段段连续的缓冲区组成,类似一个分块的数组。

  • 没有reserve()/capacity()的概念(与vector不同)。

  • 迭代器比vector复杂,但使用方式类似。


2. 声明与初始化

方式说明示例
deque<T> dq;空 dequedeque<int> dq;
deque<T> dq(n);包含 n 个值初始化的元素deque<int> dq(10);
deque<T> dq(n, val);包含 n 个值为 val 的元素deque<int> dq(5, 3);// [3,3,3,3,3]
deque<T> dq{1,2,3};(C++11)列表初始化deque<int> dq{1,2,3};
deque<T> dq(begin, end);迭代器区间构造deque<int> dq(v.begin(), v.end());
deque<T> dq(other);拷贝构造deque<int> dq2(dq1);
deque<T> dq(move(other));移动构造(C++11)deque<int> dq2(move(dq1));

cpp

deque<int> d1; // 空 deque<int> d2(10); // 10个0 deque<int> d3(5, 100); // 5个100 deque<int> d4 = {1,2,3,4,5}; // 列表初始化 vector<int> v = {10,20,30}; deque<int> d5(v.begin(), v.end()); // {10,20,30}

3. 常用操作

3.1 大小与状态

函数说明
size()元素个数
empty()是否为空
max_size()最大可能容纳的元素个数
resize(n, val)改变大小为 n,新元素用 val 填充(默认值初始化)

注意:deque没有capacity()reserve(),因为其内存不是连续的单一数组。

3.2 插入元素

函数说明时间复杂度
push_back(val)尾部插入摊销 O(1)
push_front(val)头部插入摊销 O(1)
pop_back()删除尾部元素O(1)
pop_front()删除头部元素O(1)
insert(pos, val)在迭代器 pos 前插入 valO(n)
insert(pos, n, val)插入 n 个 valO(n)
insert(pos, begin, end)插入区间O(n)
emplace_back(args...)(C++11)尾部原位构造摊销 O(1)
emplace_front(args...)(C++11)头部原位构造摊销 O(1)
emplace(pos, args...)在 pos 前原位构造O(n)

cpp

deque<int> dq = {2, 3}; dq.push_front(1); // 头部插入 1 → {1,2,3} dq.push_back(4); // 尾部插入 4 → {1,2,3,4} dq.pop_front(); // 删除头部 → {2,3,4} dq.pop_back(); // 删除尾部 → {2,3} dq.insert(dq.begin() + 1, 99); // 在索引1前插入99 → {2,99,3} dq.emplace_front(0); // 头部构造0 → {0,2,99,3}

3.3 删除元素

函数说明时间复杂度
erase(pos)删除迭代器指向的元素,返回下一个元素的迭代器O(n)
erase(first, last)删除区间,返回 lastO(n)
clear()清空所有元素O(n)

cpp

dq.erase(dq.begin()); // 删除第一个元素 dq.erase(dq.begin(), dq.begin()+2); // 删除前两个元素 dq.clear(); // 清空

3.4 元素访问

函数说明
operator[]下标访问,不检查越界
at()下标访问,检查越界(抛out_of_range
front()返回首元素引用
back()返回尾元素引用

cpp

deque<int> dq = {10,20,30,40}; cout << dq[0]; // 10 cout << dq.at(1); // 20 dq.front() = 100; // 修改首元素 dq.back() = 400; // 修改尾元素

3.5 迭代器

deque提供随机访问迭代器,支持+-++--[]等操作。

函数说明
begin()/end()正向迭代器
rbegin()/rend()反向迭代器
cbegin()/cend()常量正向迭代器

cpp

for (auto it = dq.begin(); it != dq.end(); ++it) cout << *it << " "; for (int x : dq) cout << x << " "; // 范围 for for (auto rit = dq.rbegin(); rit != dq.rend(); ++rit) // 反向遍历

3.6 其他操作

  • assign(n, val):替换为 n 个 val

  • assign(begin, end):替换为区间内容

  • swap(other):交换两个 deque 的内容(O(1))

  • 比较操作符(==,!=,<,<=,>,>=):按字典序比较元素

cpp

dq.assign(5, 10); // 5个10 dq1.swap(dq2); // 交换内容 if (dq1 == dq2) { ... }

4. deque 与 vector 的对比

特性dequevector
内存布局分段连续(多个缓冲区)单个连续数组
头部插入/删除O(1)高效O(n) 低效(需移动所有元素)
尾部插入/删除O(1) 高效均摊 O(1) 高效
中间插入/删除O(n)O(n)
随机访问O(1) 支持O(1) 支持(可能稍快)
内存重分配无需整体重新分配扩容时可能重新分配并移动全部元素
reserve()/capacity()不支持支持
迭代器失效规则更复杂(见后文)插入可能使全部迭代器失效
内存开销稍高(维护分段指针)较低(仅连续内存)

选择建议

  • 只需要在尾部操作 →vector(更简洁、内存更紧凑、随机访问可能更快)。

  • 需要在头尾两端频繁操作 →deque(更高效)。

  • 需要在头部操作且次数不多 → 两者都可,但vectorinsert在头部会 O(n),可能成为瓶颈。

  • 对内存连续性有要求(如传给 C 风格数组) → 只能用vectordeque无法保证连续内存)。


5. 性能与内存

操作时间复杂度说明
头尾插入/删除摊销 O(1)常数时间(实际可能稍慢于 vector 的尾部操作)
中间插入/删除O(n)移动元素
随机访问O(1)常数时间,但比 vector 慢一点点(需计算块索引)
遍历O(n)逐元素访问

内存特点

  • deque通常由若干固定大小的块(如 512 字节)组成,每次分配新块时不会导致已有元素移动。

  • 因此没有“容量”概念,也不需要reserve()

  • 内存占用略高:需要维护一个中控器(map)来指向各个块。


6. 迭代器失效规则

相比vectordeque的迭代器失效规则更复杂,但总体上更稳定

操作迭代器失效情况
在头部或尾部插入 (push_front/push_back)所有迭代器失效(因为可能引起中控器重新分配?实际标准:dequepush_front/push_back不会使任何已有元素的引用失效,但迭代器可能失效。具体:C++标准说插入操作会使所有迭代器失效,但引用仍然有效。不同实现有差异,最安全的假设是迭代器都会失效,但引用和指针不会失效,除非插入导致中控器重新分配。为安全编程,插入后应重新获取迭代器。)
在中间插入 (insert)所有迭代器失效
删除元素 (erasepop_front/pop_back)被删除元素以及之后的所有迭代器失效(标准规定erase会使指向被删除元素及其后元素的迭代器失效)

经验法则:在修改deque结构后(插入/删除),尽量重新获取迭代器,不要依赖旧的迭代器。


7. 完整示例

cpp

#include <iostream> #include <deque> #include <algorithm> using namespace std; int main() { // 1. 初始化 deque<int> dq = {10, 20, 30, 40}; // 2. 头尾操作 dq.push_front(5); // {5,10,20,30,40} dq.push_back(50); // {5,10,20,30,40,50} dq.pop_front(); // {10,20,30,40,50} dq.pop_back(); // {10,20,30,40} // 3. 随机访问 cout << "First: " << dq.front() << ", Last: " << dq.back() << endl; cout << "Index 2: " << dq[2] << endl; // 30 cout << "Size: " << dq.size() << endl; // 4. 中间插入 auto it = dq.begin() + 2; dq.insert(it, 25); // 在索引2前插入25 → {10,20,25,30,40} // 5. 遍历 cout << "Elements: "; for (int x : dq) cout << x << " "; cout << endl; // 6. 删除指定值(使用 erase-remove 惯用法) dq.erase(remove(dq.begin(), dq.end(), 25), dq.end()); // 删除所有25 // 7. 范围遍历(反向) cout << "Reverse: "; for (auto rit = dq.rbegin(); rit != dq.rend(); ++rit) cout << *rit << " "; cout << endl; // 8. 清空 dq.clear(); cout << "After clear, empty: " << (dq.empty() ? "yes" : "no") << endl; // 9. 使用 emplace_front 构造复杂对象 deque<pair<int, string>> dqs; dqs.emplace_front(1, "one"); // 避免临时对象 dqs.emplace_back(2, "two"); for (const auto& p : dqs) cout << p.first << " -> " << p.second << endl; return 0; }

输出示例

text

First: 10, Last: 40 Index 2: 30 Size: 4 Elements: 10 20 25 30 40 Reverse: 40 30 20 10 After clear, empty: yes 1 -> one 2 -> two

8. 常见陷阱与注意事项

  1. deque没有reserve():无法预分配内存,但头尾插入一般不会导致大量元素拷贝。

  2. 随机访问性能略低于vector:因为需要计算块索引和偏移,但通常差异不大。

  3. 中间插入/删除很慢:与vector一样为 O(n),不要误以为双端队列中间操作也很快。

  4. 迭代器失效要注意:插入或删除后,尽量重新获取迭代器,避免使用旧迭代器。

  5. 内存占用deque可能比vector多占用一些内存,尤其是元素数量较大时。

  6. deque<bool>不存在特化:没有vector<bool>那样的位压缩问题,因此deque<bool>的行为是正常的。

  7. vector的互换场景:如果你当前使用vector并在头部频繁插入,考虑改用deque;如果只需要尾部操作且对内存连续性有要求(如调用 C 函数期望数组),则继续用vector


9. 总结

  • deque是一个支持双端高效插入/删除支持随机访问的序列容器。

  • 适用于需要频繁在头尾操作的场景(如队列、滑动窗口、生产者消费者模型)。

  • 中间操作 O(n),不适合作为链表替代品。

  • 没有reserve()/capacity(),但头尾插入不引起整体元素移动。

  • vector形成互补:尾部操作用vector,头尾都用则用deque

如需更详细参考(包括分配器、C++17/20 新特性如extract等),请查阅 cppreference.com - std::deque。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/10 12:38:08

MoeCTF2025 Rush 题解|GIF逐帧隐写+残缺二维码修复全流程(Misc入门)

0. 前言MoeCTF2025 的 Rush 是一道非常经典的CTF入门级Misc隐写题目&#xff0c;结合了 GIF动态帧隐写、残缺二维码修复、图像纠错等核心考点。题目难度不高&#xff0c;无复杂加密算法&#xff0c;主要考察选手对动态图片隐写的认知、二维码基础结构认知以及手工修复能力。很多…

作者头像 李华
网站建设 2026/6/10 12:38:08

计算机中的核心硬件详解

文章目录计算机中的核心硬件详解一、计算机的基本构成1.1 冯诺依曼结构1.2 现代计算机的物理组成二、CPU三、总线四、存储器1. 存储介质和存储器2. 缓存五、I/O 设备5.1 I/O 交互方式计算机中的核心硬件详解 一、计算机的基本构成 1.1 冯诺依曼结构 任何一台现代计算机&…

作者头像 李华
网站建设 2026/6/10 12:38:03

FPG财盛国际:从工具可用性切入的框架分析

FPG财盛国际&#xff1a;从工具可用性切入的框架分析对新手与注重稳健体验的外汇内容读者而言&#xff0c;“能看懂”往往比“堆概念”更重要。围绕FPG财盛国际&#xff0c;以下重点写清解释是否通俗、规则是否易查、提示是否前置&#xff0c;以及服务是否具备连续性。在外汇相…

作者头像 李华
网站建设 2026/6/10 12:38:03

上海系统门窗哪个厂家好

上海系统门窗市场中&#xff0c;有多个厂家因其卓越的产品性能、优质的服务以及良好的用户口碑而备受推崇。以下是几个在上海市场表现优异的系统门窗厂家&#xff0c;它们在产品质量、技术创新、本地化服务等方面都具有显著优势&#xff1a;米瑞格门窗 (Mirrage Windows & …

作者头像 李华
网站建设 2026/6/10 12:34:20

徐州沐明眼镜:以专业守护儿童清晰视界,深耕近视防控的初心之路

在徐州&#xff0c;为孩子选择一家专业靠谱的眼镜店是众多家长的心愿。而徐州沐明眼镜苏宁广场店&#xff0c;凭借其专业的服务、丰富的产品以及先进的设备&#xff0c;成为了徐州儿童配镜的首选门店&#xff0c;同时也是徐州鹰瞳视康仪推荐门店。接下来&#xff0c;让我们详细…

作者头像 李华