2009-08-11 108 views
55

我需要遍历std::queue。 www.cplusplus.com说:std ::队列迭代

默认情况下,如果没有为特定队列类指定容器类,则使用标准容器类模板deque。

那么我可以以某种方式进入队列的底层deque并迭代它吗?

回答

56

如果您需要迭代queue,那么您需要的不仅仅是队列。标准容器适配器的要点是提供最小的界面。如果您还需要进行迭代,那么为什么不使用deque(或list)呢?

+73

虽然我知道你在说什么,但我总是不喜欢这种措辞“不止是一个队列”。枚举队列仍然是一个队列...此外,观察'deque'恰好支持枚举的方式,完全是任意的。你可能会认为''deque''应该和'queue'一样纯粹,不支持迭代,如果你想迭代它,那么你想要更多的东西;例如'deque_enumerable'。尽管这是一个滑坡,我个人的感觉是,“队列”应该首先支持列举。 – 2010-05-31 10:37:42

+4

@romkyns:如果我改述它会更好:“你需要一个比'queue'接口更丰富的接口,所以你应该选择一个具有合适接口的对象。不管喜不喜欢,迭代都不是“队列”接口的一部分,所以如果你想迭代,你需要选择其他的东西。 – 2010-05-31 12:28:43

+1

由于我的用例需要一个队列,但我需要将其转储出来以用于调试和日志记录目的。假设海报不知道他们在做什么通常不具有建设性。 – EML 2017-03-02 09:03:31

-2

总之:第

有一个hack,使用矢量作为垫层的容器,所以queue::front将返回有效的参考,将其转换为指针的迭代,直到< = queue::back

+0

但是,你不如直接使用矢量代替... – 2009-08-11 09:04:14

+1

你也可以直接使用deque - 包含所有必要的方法作为队列,但也支持迭代 – Dewfy 2009-08-11 09:16:51

0

如果您需要遍历队列...队列不是你需要的容器。
你为什么选择一个队列?
你为什么不带一个你可以迭代的容器?


1.如果您选择一个队列,然后你说你想包装容器为“排队”界面: - 前 - 回 - 推 - 弹出 - ...

如果您还想迭代,则队列的接口不正确。队列是提供原始容器的限制的子适配器

2.队列的定义是一个FIFO,并通过定义一个FIFO不迭代

+24

我不是OP,但这里是我的答案,以防万一有人好奇:1)我选了一个队列,因为我想要一个队列。我想在一端排队并在另一端排队。这不是一个合理的选择吗? 2)“队列”不是可枚举的,也不是显而易见的。如果你解释使用哪个容器,你的答案会更有帮助。 – 2010-05-31 10:50:57

28

虽然我与其他人同意,直接使用的可迭代的容器是一个首选的解决方案,我想指出的是,C++标准可以保证为自己动手的解决方案提供足够的支持,以防出于任何原因需要它。

即,您可以继承std::queue并使用其受保护成员Container c;来访问底层容器的begin()和end()(前提是此类方法存在)。这是在2010年和tested with ideone VS工作的例子:

#include <queue> 
#include <deque> 
#include <iostream> 

template<typename T, typename Container=std::deque<T> > 
class iterable_queue : public std::queue<T,Container> 
{ 
public: 
    typedef typename Container::iterator iterator; 
    typedef typename Container::const_iterator const_iterator; 

    iterator begin() { return this->c.begin(); } 
    iterator end() { return this->c.end(); } 
    const_iterator begin() const { return this->c.begin(); } 
    const_iterator end() const { return this->c.end(); } 
}; 

int main() { 
    iterable_queue<int> int_queue; 
    for(int i=0; i<10; ++i) 
     int_queue.push(i); 
    for(auto it=int_queue.begin(); it!=int_queue.end();++it) 
     std::cout << *it << "\n"; 
    return 0; 
} 
+1

所以我们可以对'priority_queue'做同样的事情吧? – Deqing 2014-02-07 04:15:22

+3

@Deqing:对;但是遍历底层容器并不是优先顺序。 – 2014-02-07 10:48:11

+0

为什么重新定义一个新的类而不直接使用'deque'? – 2018-01-16 05:55:58

-2

std::queue是一个容器适配器,您可以指定使用的容器(默认为使用deque)。如果您需要超出适配器的功能,那么只需使用deque或其他容器。

+3

虽然你的回答是正确的,但是完全没有必要,因为这个2岁的问题已经有两个答案完全相同(其中一个答案是被接受的答案)。 – 2012-12-04 16:04:02

0

为什么不直接复制要迭代的队列,并一次删除一个项目,随时打印它们?如果你想在迭代中对元素做更多的事情,那么队列就是错误的数据结构。

+2

呃,没有。复制然后销毁一个队列的方式比你需要的开销更多。这就是迭代器被发明的原因。 – Mac 2012-12-04 22:15:48

+1

简单:创建空队列。将每个项目从主队列中弹出,直到空,根据需要进行处理,然后将其推送到空队列中。完成后,将主队列设置为等于空队列。也适用于priority_queue。警告:如果某个其他线程试图同时访问队列,则不是线程安全的。另外,如果您的原始文件是堆分配的(通过'malloc' /'new'创建的),一定要'释放'''删除它,否则你会泄漏内存。 – 2015-10-28 21:16:19

3

您可以将原始队列保存到临时队列中。然后,你只需做临时队列您的正常弹出要经过原之一,例如:

queue tmp_q = original_q; //copy the original queue to the temporary queue 

while (!tmp_q.empty()) 
{ 
    q_element = tmp_q.top(); 
    std::cout << q_element <<"\n"; 
    tmp_q.pop(); 
} 

在年底,tmp_q将是空的,但是原来的队列不变。

+0

'std :: queue'似乎没有'.top()'方法 – 2018-01-19 09:15:46