2009-08-11 127 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