迭代器

目前為止,提供的 fbl:: 有許多用途範例。 疊代器fbl:: 中的疊代器使用的 API 與 std:: 容器,希望您會對這些內容感到熟悉。沒錯, 但能花點時間說明 除了支援 fbl:: 疊代器外,也支援 std:: 疊代器。

iteratorconst_iterator

std:: 疊代器一樣,fbl:: 疊代器提供兩種變種版本,也就是一個非常數的 和常數版本begin()find() 等作業會傳回 以下情況使用簡易疊代器: 非 const,否則為 const_iterator。已執行解除參照作業 在 const_iterators 上,請授予 const T&,因此 const 可存取 基礎物件

begin()/end()

std:: 一樣,容器上的 begin() 方法會將疊代器傳回 容器中第一個元素,而 end() 則會將疊代器傳回 元素的第一個元素開頭和結尾 在 const 參照上呼叫時,會自動傳回 const_iterator 但由於應用程式在容器載入時 可能會使用 cbegin()/cend() const_iterator 是明確使用 都會在 Docker 容器中執行

疊代器比較和預設初始化疊代器與 end() 的比較

std:: 一樣,所有 fbl:疊代器支援使用 == 測試相等性 和 != 運算子。與 std:: 不同,所有疊代器皆無法隨機存取 不支援疊代器語意和 >>=<<= 運算子 適用於任何 fbl:: 容器iterator 類型。

此外,預設的初始化之間有些微差異 對容器 end() 方法的呼叫傳回的疊代器和疊代器。 從語意的角度來看,它們都相同。預設初始化的疊代器和 end() 的值無效,因此兩者的比較會傳回 true。 然而,兩個執行個體包含的位元不同。請一律使用 比較運算子來測試兩個疊代器之間的相等性。

fbl::DoublyLinkedList<Obj*> the_list;
fbl::DoublyLinkedList<Obj*>::iterator default_init;
auto end_init = the_list.end();

if (default_init == end_init) { }                            // This comparison is true
if (!memcmp(&default_init, &end_init, sizeof(end_init))) { } // This is not.

疊代器進展

所有疊代器都支援 ++ 運算子的前和後後形式。 前置字串表單會將疊代器移至序列中的下一個元素 會傳回疊代器副本,指向下一個元素。修正後 表單在傳回時,會將疊代器移至序列中的下一個元素 預先進階疊代器的副本

// Assuming that the list starts containing objects with values
// "5 7 9", in that order.
fbl::DoublyLinkedList<Obj*> the_list;
auto iter   = the_list.begin();   // iter points to "5".
auto second = iter++;             // iter points to "7", but second points to "5"
auto third  = ++iter;             // iter points to "9", and so does third
++iter;                           // iter is now equal to the_list.end()

DoublyLinkedList 的疊代器、HashTable 具有雙連結清單值區的疊代器, WAVLTree 都支援透過 -- 運算子進行雙向疊代 。SinglyLinkedListHashTable,其中包含 安全連結的清單值區不會。

將疊代器移至容器結尾後,就會產生 container.end()。 嘗試進一步發展是合法性,但並不會改變 iterator。備份目前設為下列方向的雙向疊代器 使用 -- 運算子的 container.end() 會產生疊代器, 至清單的最後一個元素,但備份已產生的疊代器 。而是改為在++-- 初始化的預設值會讓疊代器處於預設的初始化狀態。 最後,備份值等於 container.begin() 的疊代器會 產生值等於 container.end() 的疊代器。隨後 -- 的應用程式會按反向順序瀏覽元素,從 與最後一個元素

將疊代器取消參照

fbl:: 容器中的元素一律為物件,因此一律支援 -> 運算子和一元 * 運算子。兩者都會產生 T&const T& (->隨後會存取成員), iterator 是 const_iterator 或不可能的值。

試圖延遲無效的疊代器是非法行為, 視事件的性質而定,觸發 ZX_DEBUG_ASSERT 或未定義的行為 建構過程

使用 container::make_iterator(),透過物件建立疊代器

容器具有乾擾性,因此可以建立 容器疊代器舉例來說 會由索引鍵排序的物件樹狀結構、接受物件並傳回 或是對該物件的參照,或是說 例如:

using ObjectTree = fbl::WAVLTree<uint64_t, fbl::RefPtr<Object>>;

fbl::RefPtr<Object> FetchPrior(ObjectTree& tree, Object& obj) {
  ZX_DEBUG_ASSERT(obj.InContainer());
  auto iter = tree.make_iterator(obj);
  return (--iter).IsValid() ? iter.CopyPointer() : nullptr;
}

iterator::IsValid()

系統可能會使用 IsValid 測試所有 fbl:: 疊代器執行個體是否有效 方法。在這個步驟中測試疊代器是否有效 等於測試 iter != container.end(),但 IsValid 方法可能會產生有效率的程式碼,但實際情況取決於 以及編譯器在實作中的 容器的 end() 方法

iterator::CopyPointer()

最後,fbl:: 疊代器提供稱為 CopyPointer 的方法,可以 來產生容器所用指標類型的副本適用對象 原始指標的容器,這也很簡單它只是物件的 T* 副本 指向物件的指標。事實上,iter.CopyPointer() == &(*iter) 應一律 對原始指標的值為 true

對於具有專屬語意的代管指標,CopyPointer 概不法律規定。正在嘗試 對使用 std::unique_ptr 追蹤的物件容器呼叫 CopyPointer 會產生錯誤

最後,當 CopyPointer 針對容器容器的疊代器執行時 可複製的代管指標,系統會使用 指標類型的複製建構函式。也就是說,它會產生一個 物件的代管參照。

嘗試對無效疊代器呼叫 CopyPointer 至可複製的指標 類型會產生 nullptr