0
点赞
收藏
分享

微信扫一扫

C++ std::queue:高效处理先入先出的数据

C++ std::queue:高效处理先入先出的数据

在程序世界里,很多场景都需要按照 “先来后到” 的规则处理数据 —— 比如打印任务排队、消息队列传递数据、广度优先搜索中的节点遍历。这时,std::queue就能派上大用场,它像一条两端通透的管道,数据从一端进入,从另一端按顺序流出,完美贴合 “先入先出” 的业务需求。

先看一个简单的打印任务模拟,感受std::queue的基本用法:

#include <iostream>
#include <queue>
#include <string>
using namespace std;

int main() {
    // 创建一个存储字符串的队列,模拟打印任务列表
    queue<string> print_tasks;
    
    // 添加打印任务(入队操作)
    print_tasks.push("简历.pdf");
    print_tasks.push("报告.docx");
    print_tasks.push("图片.png");
    
    // 查看队列中有多少任务
    cout << "当前等待打印的任务数:" << print_tasks.size() << endl;
    
    // 处理任务(出队操作),按添加顺序依次处理
    while (!print_tasks.empty()) {
        // 查看队首任务(不删除)
        cout << "正在打印:" << print_tasks.front() << endl;
        // 移除队首任务(已完成)
        print_tasks.pop();
    }
    
    // 确认队列已空
    if (print_tasks.empty()) {
        cout << "所有打印任务已完成!" << endl;
    }
    
    return 0;
}

这段代码清晰展示了std::queue的核心操作:push()添加元素到队尾,front()获取队首元素,pop()移除队首元素,size()查看元素数量,empty()判断队列是否为空。这些操作组合起来,就能轻松实现各种排队场景。

std::queue的内部结构默认基于std::deque实现,这让它在两端操作时效率极高。如果你需要严格控制内存分配,也可以指定其他底层容器,只要该容器支持back()、push_back()、front()、pop_front()和empty()操作即可,比如用std::list作为底层:

// 使用list作为底层容器的队列
queue<int, list<int>> custom_queue;
custom_queue.push(10);
custom_queue.push(20);
cout << custom_queue.front() << endl; // 输出10

在多线程通信中,std::queue常被用来实现生产者 - 消费者模型。比如一个线程生成数据(生产者),另一个线程处理数据(消费者),队列就像两者之间的缓冲区:

#include <thread>
#include <mutex>
#include <condition_variable>

queue<int> data_queue;
mutex mtx;
condition_variable cv;
bool finished = false;

// 生产者:生成数据并放入队列
void producer() {
    for (int i = 0; i < 5; ++i) {
        {
            lock_guard<mutex> lock(mtx);
            data_queue.push(i);
            cout << "生产数据:" << i << endl;
        }
        cv.notify_one(); // 通知消费者有新数据
        this_thread::sleep_for(chrono::milliseconds(100));
    }
    
    // 标记生产结束
    {
        lock_guard<mutex> lock(mtx);
        finished = true;
    }
    cv.notify_one();
}

// 消费者:从队列中取出数据并处理
void consumer() {
    while (true) {
        unique_lock<mutex> lock(mtx);
        // 等待数据或生产结束
        cv.wait(lock, []{ return !data_queue.empty() || finished; });
        
        // 如果生产结束且队列空,则退出
        if (finished && data_queue.empty()) break;
        
        // 处理数据
        while (!data_queue.empty()) {
            cout << "消费数据:" << data_queue.front() << endl;
            data_queue.pop();
        }
    }
}

int main() {
    thread prod(producer);
    thread cons(consumer);
    
    prod.join();
    cons.join();
    return 0;
}

这个例子中,队列安全地在两个线程间传递数据,配合互斥锁和条件变量,完美解决了生产者和消费者的协作问题。

std::queue的设计哲学是 “简单专一”—— 它只提供必要的接口,隐藏了复杂的实现细节。这种特性让它在处理排队场景时既高效又易用,避免了手动实现队列时容易出现的内存泄漏、越界访问等问题。无论是模拟现实中的排队场景,还是实现程序内部的缓冲机制,std::queue都能以简洁的代码完成任务,是 C++ 开发者处理顺序数据的得力工具。

举报

相关推荐

0 条评论