1. queue概念

     queue是一种提供FIFO(先进先出)行为的标准容器,它满足容器的大多数要求。本质它不是真正的容器,而是一个适配器。因为它并未定义与迭代器有关的任何内容及接口。它持有另一个容器,并为该容器提供包装器接口。包装器强制执行严格的先进先出队列行为。第二个模板参数定义了底层序列/容器的类型。它的默认值是std::deque,但是它可以是任何支持 front、 back、push_back和 pop_front的类型,比如std::list或适当的用户定义类型。queue的定义可以参见 stl_queue.h 。即:template <class T,class Container = deque <T>> class queue;
在这里插入图片描述                                   图1 queue容器示意图
     当size() = 0时候,empty()为true。

2. queue成员函数

·empty() 判断queue容器是否为空
·size() 返回当前queue容器的大小(既有多少元数据)
·front() 访问queue容器的第一个(首部)元素
·back() 访问queue容器的(尾部)最后一个元数据
·push() 向queue容器中插入新的元数据
·emplace() 构造并插入元数据
·pop() 删除下一个元数据
·swap() 交互两个queue容器的内容
     

2.1 queue示例程序

     该示例程序演示了queue队列中各成员函数的使用规则。

queue<int> qList; //1. 创建一个空的queue队列
queue<int> bList;
for(int i = 0; i < 10; ++i)
{
	qList.push(i + 1);  //2. 向队列qList中插入10个元数据
}

cout<<"--------------------------------------"<<endl;
//3. 输出qLis队列的大小,共包含了10个元数据
cout<<"qList size: "<<qList.size()<<endl; 
//4. 判断qList队列是否为空, 若为空--true(1), 不为空--false(0)
cout<<"qList empty: "<<qList.empty()<<endl;
//5. 输出qList队列的所有元数据,前提条件是当其不为空时
while(!qList.empty())
{
	//6. 输出qList队列的第一个(队首)元素
	cout<<qList.front()<<" ";
	//7. 将队首元数据从当前qList队列中移除掉(删除)
	qList.pop();
}
cout<<endl;
cout<<"--------------------------------------"<<endl;
//8. 再次打印队列qList的大小, 因为前面已经全部移除掉,因此这里大小是0
cout<<"qList size(2): "<<qList.size()<<endl;
//9. bList队列采用默认初始化,因此没有元数据,其大小为0
cout<<"bList size: "<<bList.size()<<endl;
//10.bList队列为空
cout<<"bList empty: "<<bList.empty()<<endl;
cout<<"--------------------------------------"<<endl;
//11. 构造数据向qList中插入数字1,3,5
qList.emplace(1);
qList.emplace(3);
qList.emplace(5);

//12. 交换两个容器的数据,此后,qList大小为0, 则bList队列大小为3.
bList.swap(qList);
//13. bList队列大小为3
cout<<"bList size: "<<bList.size()<<endl;
//14. bList容器有3个元数据,因此,不为空=0
cout<<"bList empty: "<<bList.empty()<<endl;
cout<<"--------------------------------------"<<endl;
while(!bList.empty())
{
	cout<<bList.front()<<" ";
	bList.pop();
}
cout<<endl;
cout<<"--------------------------------------"<<endl;

     该示例程序的输出结果是:

--------------------------------------
qList size: 10
qList empty: 0
1 2 3 4 5 6 7 8 9 10
--------------------------------------
qList size(2): 0
bList size: 0
bList empty: 1
--------------------------------------
bList size: 3
bList empty: 0
--------------------------------------
1 3 5
--------------------------------------

     

3. queue应用场景

     队列queue的底层实现采用的deque。关于queue队列,它的主要特性是FIFO(先进先出),结合它的内部结构和功能特征分析,队列queue适合用来做“异步处理、应用解耦、流量削峰、日志处理和消息通讯”,项目中用的最多的是生产者、消费者模式,将非核心流程异步化,提高系统响应性能。比如某线程从kafka消费出来的批量数据它只需要将其放到某个缓存队列中,然后有后台线程专门负责从该缓存队列里面取数据进行相应处理,是入库?还是其他义无逻辑处理,对消费kafka数据的线程来说,它并不关心,也无需等待底层义务处理情况。这样的异步处理设计具有弱耦合性,提供系统性能。

在这里插入图片描述
                                        图来自 shilod
     

4. queue源码

4.1 如何获取queue源码

     如果希望对STL(标准模板库)有着更深的理解和认识,最好的方法就是先熟悉理论知识,知道顺序容器、关联容器都分别有哪些,然后每个容器的优缺点,或说是特性。然后源码阅读,理论联系实际,这样对STL的掌握和见解有着更深一层的提高。首先STL仅是一个C++标准里规定的接口规范,并没有具体实现,因此每个平台上面的编译器都会有着自己的STL的实现。如何获取STL相关源码?你可以参考知乎的这篇博客 这么多款STL,总有一款适合你 。介绍挺详细的,很具有参考意义。

     我阅读的是GNU/gcc-9.1.0编译器下的STL源码, Index of /gnu/gcc 中列出了历代(v1.42~v9.3.0)gcc编译器的版本下载列表。根据自己需要选择下载对应版本。
在这里插入图片描述
     

4.2 关于queue实现

     
     
     

5. queue如何有效清空内存空间

     从上面2.1小节中示例代码可看到,删除queue队列中元数据的方式是使用成员函数pop() 。即一直不断循环删除队列头中的元数据,直到该queue队列为空为止。常规写法如下:

queue<int> qList; 
while(!qList.empty()) qList.pop();  //移除queue队列首部元数据,直到为空

     除此方法外,有没有一种不需判断N次(即队列有N个元素据)即可达到删除队列中全部元数据的方法?这个在stackoverflow上面有一篇专门讨论该话题的文章 如何有效清除std::queue?
     实例化一个临时的空队列与其进行交换,即:queue<int>().swap(qList); 备注:swap函数好像在C++11的queue中才有该成员函数。
     也可以直接将其赋值为空。queue<int> qList; qList = {};。对于这几种删除queue队列元数据的方法,在其效率上我没有去实测过,具体哪一种高效,还需以实测结果为准。
     

I found that swapping in C++03 version works 70-80% slower than assignment to an empty object. In C++11 there is no difference in performance

6. queue线程安全吗?

     在4.1节中提到过STL仅是C++提供的一套接口规范,每个编译器厂商的具体实现都有可能不同,因此C++本身是不提供任何关于STL中各容器的线程安全问题的方案的。这个需要STL库使用者自己去保证。cplusplus.cm 中也有专门的一节话题来讨论关于 STL thread safety 问题。下面我们写一个demo来测试下当多个(两个)线程往queue读,一个队里向里面写的时候,是否会出现异常。
     

     
     
     

7. 总结

     
     
     
     
     
     
     

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐