[英]Why const_iterator does not provide a base like reverse_iterator?
[英]Why is reverse_iterator::base offset?
+-- v.begin() +-- v.end()
| |
v v
+---+---+---+---+---+---+ - +
| o | o | o | o | o | o | x |
+---+---+---+---+---+---+ - +
+ - +---+---+---+---+---+---+
| x | o | o | o | o | o | o |
+ - +---+---+---+---+---+---+
^ ^
| |
+-- v.rend() +-- v.rbegin()
(ASCII 從這個答案復制和編輯,這實際上促使我問現在的問題。)
我確實看到了&*rit == &*(rit.base() - 1)
的優勢,因為這樣我就可以為任何反向迭代器rit
使用rit.base()
並且我總是會得到一個有效的迭代器。
但同時
v.rbegin().base()
; 我必須記住先減去 1, *(v.rbegin().base() - 1)
,v.rend().base() - 1
正是因為我不能取消引用v.rend()
。 如果設計是&*rit == &*rit.base()
怎么辦?
v.rend().base()
,是的,但這僅僅對應於不能在當前設計中取消引用v.rend().base() - 1
;v.end()
,甚至是最接近的迭代器b.rbegin()
,但對於- 1
我們必須添加到rit.base()
中當前的設計是將正向迭代器指向與反向相同的元素。 我的意思是,在我看來,設計決定是&*rit == &*(rit.base() - 1)
(原樣)還是&*rit == &*rit.base()
,我們會有同樣多的便利
rit.base()
在實際設計中總是可以的,- 1
在替代設計中通常不需要和不便
rit.base()
,+1
v.rbegin()
才能在替代設計中獲得v.end()
,只是在相反的情況下。
所以我的問題是:做出確實已經做出的選擇是否有明確的優勢? 或者它只是一個翻轉的硬幣?
我看到在第一個元素之前沒有有效的迭代器,但這就是我的意思。 當引入反向迭代器時,讓std::prev(v.begin())
像v.end()
一樣成為有效的、不可解引用的迭代器會有什么問題?
事后看來,我確實看到了一個毋庸置疑的優勢。
我沒有看到v.rbegin().base() == v.end()
/ v.rend().base() == v.begin()
的優勢,因為我為什么要創建v.end()
/ v.begin()
來自他們的反向對手?
但是,如果我有兩個定義范圍(rit1, rit2]
的反向迭代器rit1
和rit2
,那么采用it1 = rit1.base()
和it2 = rit2.base()
可以輕松地引用相反范圍內的相同元素方向, [it1, it2)
。
長話短說:_我應該閱讀The C++ Standarl Library - 2nd ed 中的 §9.4.1。 第一的。
這不是設計決定,而是必然。
反向迭代器並不是某種能夠以某種方式反向迭代范圍的神奇事物。 它是建立在已經存在的事物之上的立面。
當您有一個包含 6 個條目的集合時(如您的圖片所示),那么您所擁有的只是 7 個可用的迭代器值,僅此而已(6 個是可取消引用的,一個是結束迭代器值)。 這就是反向迭代器可以構建的全部內容。
由於沒有先於開始的迭代器(就像第二張圖片讓人想到的那樣),因此對於反向迭代器,除了將 map rbegin()
到end()
和rend()
到begin()
之外別無選擇。 也就是說,你有(rbegin() + i).base() == end() - i
這反過來又要求可取消引用的迭代器(從rbegin()
開始的前 6 個)實際上必須取消引用迭代器.base()-1
。 沒有其他方法可以實現反向迭代器。
在當前設計中,所有這些都按預期工作:
std::make_reverse_iterator(it).base() == it;
auto rbegin = std::make_reverse_iterator(end);
auto rend = std::make_reverse_iterator(begin);
在您的替代設計中,不可能所有的人都持有。 如果 base &*rit == &*rit.base()
那么
要么你必須構造一個偏移量:
auto last = std::prev(end) auto rbegin = std::make_reverse_iterator(last); auto pastbegin = std::prev(begin); // not allowed: auto rend = std:;make_reverse_iterator(pastbegin);
這將需要將迭代器的概念引入到不存在的“第一個元素之前”。 std::prev(begin)
在當前設計中是不允許的,並且允許它會使迭代器是指針的 arrays 的反向迭代器變得不可能,因為該語言禁止在第一個元素之前創建指針。
或者你必須在施工后抵消
auto rpastbegin = std::make_reverse_iterator(end); auto rbegin = std::next(rpastbegin); auto rlast = std::make_reverse_iterator(begin); auto rend = std::next(rlast);
這種方法只需要為反向迭代器引入 past begin。 由於它們不是指針,理論上這可能是可能的,但這將需要額外的開銷來表示比基本迭代器更多的迭代器狀態。
這兩種選擇都不是特別方便使用。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.