2012-06-27 73 views
10

我正在製作一個C++ 11類,它產生大量的數據。該數據當前來自數據庫,並且不能完全適合內存。我想爲用戶提供一個像普通STL迭代器一樣的迭代器,但這會很懶。更確切地說,我將能夠做這樣的事情:我怎樣才能讓自己的懶惰迭代器?

for (auto& item : big_bunch_of_data) { 
    do_stuff_with(item); 
} 

隨着項目正在從數據庫中只在每次迭代檢索。如果我是正確的,這個新的語法糖

for (stuff::iterator it = big_bunch_of_data.begin();it != big_bunch_of_data.end();it++) { 
    do_stuff_with(*it); 
} 

這是否意味着通過提供beginendoperator++,我可以有期望的行爲?而且,這些方法應該做什麼?我的意思是,我可以讓他們懶惰而不打破東西嗎?

+1

_「該數據當前來自數據庫,並且不能完全適合內存」_因此,在不知道數據庫的情況下很難提供更好的建議......但請記住,許多SQL數據庫都提供了它們自己的內部迭代器機制_cursors_的形式可能對您有用。 – Rook

+1

我正在使用sqlite,但這可能會在將來發生變化,我不想向我的代碼的用戶公開原始指針,這就是爲什麼我試圖封裝它相當好(是的,已經很懶) API。 – Fabien

回答

11

差不多;如果在容器類中找不到beginend方法,編譯器會查找其他幾個位置以獲取開始和結束迭代器;這是基於範圍的循環在陣列上的工作方式,它沒有beginend成員。它還將尋找ADL的免費功能beginend,最終還有std::beginstd::end,因此有很多機會爲現有容器改裝基於範圍的循環支持。第6.5.4節涵蓋了細節。

對於你的其他問題,迭代器絕對可以是懶惰!一個很好的例子是std::istream_iterator其中懶惰,因爲它從控制檯讀取輸入。

for循環中使用的迭代器的要求是,它應當滿足輸入迭代類,這是在部分24.2.3中所述;該類別所需的操作是!=,一元*,以及前後增量++

要讓語言知道您已經創建了輸入迭代器,您應該從std::iterator<std::input_iterator_tag, T, void, T *, T &>繼承,其中T是迭代器處理的類型(第24.4.3節)。

+3

其實沒有。它直接使用'.begin()'成員函數。如果沒有找到這樣的成員,它會通過ADL使用'begin',而不一定是'std :: begin'。 –

+0

@ R.MartinhoFernandes感謝您的澄清。 – ecatmur

+0

恩,謝謝,那正是我需要的。 – Fabien