2015-06-21 74 views
4

目前,std::advance是這樣設計的:爲什麼不std :: advance返回結果迭代器?

template< class InputIt, class Distance > 
void advance(InputIt& it, Distance n); 

不過,我經常發現自己想要的東西,如:

template< class InputIt, class Distance > 
InputIt advance(InputIt it, Distance n); 

那麼,什麼是當前的設計背後的原理是什麼?這是出於某種性能考慮?請注意,std::nextstd::prev確實會返回結果迭代器。

+5

我相信這個設計需要支持輸入迭代器。 'std :: next'和'std :: prev'需要相應的前向和雙向迭代器。 –

+0

我相信他們沒有想到像這樣設計它......就像很多其他的東西一樣。 – Nawaz

+0

IDK。但是,在其他地方,我們做了一些努力來避免迭代器的多餘副本,例如post和pre increment。所以顯然有人認爲這是一個性能問題,正如你所建議的那樣。 –

回答

1

沒有任何技術原因阻止它將參考返回到輸入值,任何合理的編譯器都應該能夠優化返回值,如果不使用它。所以他們可以這樣做,如果他們想的話。

我覺得自己的選擇是有道理的從API設計的角度來看,雖然 - std::prevstd::next採取迭代器,並返回不同的迭代器,指向上一個或下一個元素,分別無需修改輸入

std::advance另一方面修改輸入。如果它返回了對輸入迭代器的引用,那麼它可能會對返回副本而不就地修改輸入的函數感到困惑。這可能是危險的。

注意std::advance作品與InputIterator s,這包括迭代器,其中迭代有副作用(的東西,如從流讀取的迭代器),但std::prevstd::next只有ForwardIterator s,這沒有副作用的工作。

於是久違的獨立(如std::prevstd::next)將是一個糟糕的主意 - 你最終與同流兩個迭代器,這可能會影響彼此不利。

+0

作爲一個解釋,這沒有意義 - 你只是重複明顯的事實。整個答案歸結爲「他們可以做到,但他們沒有」。 – BartoszKP

+0

@BartoszKP他們可以做到這一點,但他們不這樣做,因爲這不是一個好主意。我的回答解釋了爲什麼它會是一個壞主意。 – AaronI

+0

例如,第三段是適用於* any *函數的小事,不僅是'std :: advance'。如果'std :: prev'引用了一個引用,你可以說完全一樣的東西 - 返回一個引用可能會被一個函數搞糊塗,該函數返回拷貝而不修改輸入。只有關於輸入和前向迭代器(*,你剛剛添加*)的段落是相關的。所以,現在看起來好了(雖然我會刪除所有其他部分,因爲他們只是噪音,很難找到點,這只是在第4段) - 我會刪除我的意見。乾杯! – BartoszKP

0

的主要原因,如在評論部分表示的是一個InputIterator並不保證增量迭代後,以前的任何迭代器仍然有效:

InputIterators只保證有效期爲單通道算法:一旦InputIterator i被增加,其先前值的所有副本都可能失效。

因此,如果std::advance返回副本,調用者可能會以兩個迭代器結束,其中一個可能無效。帶引用的接口表明這不是應該如何使用輸入迭代器。

在另一方面std::prevstd::next採取BidirectionalIterator,其中除其他外,要滿足ForwardIterator要求:

不同於InputIterator的和輸出迭代,可以在多遍算法中使用。

所以,你可以移動一個迭代器,同時仍然保存它以前的位置的副本。

Here是一個很好的表格,清楚地表示了不同迭代器概念之間的關係。


當然,人們可能會認爲,主叫方應該知道InputIterator的是如何工作的,應當允許有選擇適合自己當前需要一個版本的方便。 dyp在評論部分提出了一個這樣的問題的例子:http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#2353

然而,每個人都喜歡,總是會導致界面中方法的數量激增。

該鏈接表明,現在是一種即將形成共識的狀態。

+1

請參閱http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#2353 – dyp

相關問題