引言:为什么 C++ 中需要任务队列?
\n想象一下,你正在超市收银台前排队。第一个到达的人,第一个被服务。在编程中,这种结构被称为 队列 (queue)。这是一种基础数据类型,遵循 FIFO (先进先出) 原则——“先来先服务”。
\n在 C++ 中,任务队列被广泛使用:从处理网络请求到管理多线程应用程序中的线程。对于初学者程序员来说,理解队列是掌握更复杂主题(如异步编程和设计模式)的一步。
\n在本文中,我们将探讨如何在 C++ 中创建和使用队列,介绍标准容器 std::queue,编写一些实际示例,并讨论初学者常犯的错误。
队列基础:理论和第一个示例
\n什么是队列?
\n队列是一种抽象数据类型,支持两种基本操作:
\n- \n
- 添加元素到队列末尾 (enqueue / push); \n
- 提取元素从队列开头 (dequeue / pop). \n
在 C++ 中,标准队列实现在头文件 <queue> 中,作为 std::queue 类。默认情况下,它使用 std::deque 作为底层容器,但你可以将其替换为 std::list。
第一个示例:数字队列
\n让我们编写一个简单的程序,创建一个整数队列,添加几个值,并将它们输出到屏幕。
\n#include <iostream>\n#include <queue>\n\nint main() {\n std::queue<int> my_queue;\n\n // 向队列添加元素\n my_queue.push(10);\n my_queue.push(20);\n my_queue.push(30);\n\n std::cout << "第一个元素 (front): " << my_queue.front() << std::endl;\n std::cout << "最后一个元素 (back): " << my_queue.back() << std::endl;\n std::cout << "队列大小: " << my_queue.size() << std::endl;\n\n // 提取元素\n while (!my_queue.empty()) {\n std::cout << "已提取: " << my_queue.front() << std::endl;\n my_queue.pop();\n }\n\n return 0;\n}\n程序运行结果:
\n第一个元素 (front): 10\n最后一个元素 (back): 30\n队列大小: 3\n已提取: 10\n已提取: 20\n已提取: 30\n请注意:front() 返回第一个元素(下一个将被提取的元素),而 back() 返回最后添加的元素。方法 pop() 删除元素,但不返回它——这一点很重要,请记住!
std::queue 的主要方法
\n为了高效使用队列,你需要了解它的所有方法。以下是完整列表:
\n- \n
push(const T& value)— 向队列末尾添加元素; \n pop()— 删除第一个元素(不返回它); \n front()— 返回对第一个元素的引用; \n back()— 返回对最后一个元素的引用; \n empty()— 检查队列是否为空(返回 true/false); \n size()— 返回元素的数量。 \n
重要提示: 在调用 front() 或 pop() 之前,始终使用 empty() 检查队列是否为空。尝试访问空队列的元素将导致未定义行为(很可能导致程序崩溃)。
实际示例:任务队列
\n现在,让我们模拟一个真实场景。假设我们有一个处理订单的系统。每个订单是一个包含编号和描述的结构体。我们将订单放入队列中