求一个关注不过分吧看在文章这么精品的份上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. 声明与初始化方式说明示例dequeT dq;空 dequedequeint dq;dequeT dq(n);包含 n 个值初始化的元素dequeint dq(10);dequeT dq(n, val);包含 n 个值为 val 的元素dequeint dq(5, 3);// [3,3,3,3,3]dequeT dq{1,2,3};(C11)列表初始化dequeint dq{1,2,3};dequeT dq(begin, end);迭代器区间构造dequeint dq(v.begin(), v.end());dequeT dq(other);拷贝构造dequeint dq2(dq1);dequeT dq(move(other));移动构造C11dequeint dq2(move(dq1));cppdequeint d1; // 空 dequeint d2(10); // 10个0 dequeint d3(5, 100); // 5个100 dequeint d4 {1,2,3,4,5}; // 列表初始化 vectorint v {10,20,30}; dequeint 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...)(C11)尾部原位构造摊销 O(1)emplace_front(args...)(C11)头部原位构造摊销 O(1)emplace(pos, args...)在 pos 前原位构造O(n)cppdequeint 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)cppdq.erase(dq.begin()); // 删除第一个元素 dq.erase(dq.begin(), dq.begin()2); // 删除前两个元素 dq.clear(); // 清空3.4 元素访问函数说明operator[]下标访问不检查越界at()下标访问检查越界抛out_of_rangefront()返回首元素引用back()返回尾元素引用cppdequeint 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()常量正向迭代器cppfor (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 个 valassign(begin, end)替换为区间内容swap(other)交换两个 deque 的内容O(1)比较操作符,!,,,,按字典序比较元素cppdq.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更高效。需要在头部操作且次数不多 → 两者都可但vector的insert在头部会 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)所有迭代器失效因为可能引起中控器重新分配实际标准deque的push_front/push_back不会使任何已有元素的引用失效但迭代器可能失效。具体C标准说插入操作会使所有迭代器失效但引用仍然有效。不同实现有差异最安全的假设是迭代器都会失效但引用和指针不会失效除非插入导致中控器重新分配。为安全编程插入后应重新获取迭代器。在中间插入 (insert)所有迭代器失效删除元素 (erase、pop_front/pop_back)被删除元素以及之后的所有迭代器失效标准规定erase会使指向被删除元素及其后元素的迭代器失效经验法则在修改deque结构后插入/删除尽量重新获取迭代器不要依赖旧的迭代器。7. 完整示例cpp#include iostream #include deque #include algorithm using namespace std; int main() { // 1. 初始化 dequeint 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 构造复杂对象 dequepairint, 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; }输出示例textFirst: 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 - two8. 常见陷阱与注意事项deque没有reserve()无法预分配内存但头尾插入一般不会导致大量元素拷贝。随机访问性能略低于vector因为需要计算块索引和偏移但通常差异不大。中间插入/删除很慢与vector一样为 O(n)不要误以为双端队列中间操作也很快。迭代器失效要注意插入或删除后尽量重新获取迭代器避免使用旧迭代器。内存占用deque可能比vector多占用一些内存尤其是元素数量较大时。dequebool不存在特化没有vectorbool那样的位压缩问题因此dequebool的行为是正常的。与vector的互换场景如果你当前使用vector并在头部频繁插入考虑改用deque如果只需要尾部操作且对内存连续性有要求如调用 C 函数期望数组则继续用vector。9. 总结deque是一个支持双端高效插入/删除且支持随机访问的序列容器。适用于需要频繁在头尾操作的场景如队列、滑动窗口、生产者消费者模型。中间操作 O(n)不适合作为链表替代品。没有reserve()/capacity()但头尾插入不引起整体元素移动。与vector形成互补尾部操作用vector头尾都用则用deque。如需更详细参考包括分配器、C17/20 新特性如extract等请查阅 cppreference.com - std::deque。