fbl::
提供兩個主要的容器系列:序列的容器
以及關聯容器
序列容器是元素列舉順序的容器
取決於使用者特別新增和移除元素的方式
fbl::
定義了兩種序列容器。
SinglyLinkedList
是支援轉送的已排序容器DoublyLinkedList
是支援雙向的序列容器
排序容器和關聯容器之間的主要差異 說明元素在容器中新增和移除的方式。 本指南的章節將說明您可以在 以及擷取自序列容器的資料
詳情請參閱設定版本 依附元件。 ,才能使用各種容器類型。
將元素新增至排序的容器
SinglyLinkedList
提供兩種在容器中新增元素的方法。
如下所示:
DoublyLinkedList
也支援這些方法,但也新增下列內容
方法。
一如以往,如果
該容器類型使用的節點狀態已經是容器的成員。
使用代管指標類型時,使用者可能會讓容器擁有自己的容器
透過值提供指標執行個體來參照物件,或
使用 std::move
將參照轉移到容器。
將元素推送至序列容器
推送方法會正常運作,新增元素並將其設為新的元素 序列的前方或後方元素 (也就是第一個或 列舉順序中的最後一個元素)。例如:
struct Tag1 {};
struct Tag2 {};
class Obj : public fbl::RefCounted<Obj>,
public fbl::ContainableBaseClasses<
fbl::TaggedDoublyLinkedListable<fbl::RefPtr<Obj>, Tag1>,
fbl::TaggedDoublyLinkedListable<fbl::RefPtr<Obj>, Tag2>
> {
public:
explicit Obj(int val) : val_(val) {}
int val() const { return val_; }
private:
const int val_;
};
TaggedDoublyLinkedList<fbl::RefPtr<Obj>, Tag1> stack_like;
TaggedDoublyLinkedList<fbl::RefPtr<Obj>, Tag2> queue_like;
for (int i = 0; i < 5; ++i) {
fbl::RefPtr<Obj> obj_ref = fbl::AdoptRef(new Obj(i));
stack_like.push_front(obj_ref); // Copy our reference
queue_like.push_back(std::move(obj_ref)); // Transfer our reference
}
// Prints "4 3 2 1 0 "
for (const auto& obj : stack_like) { printf("%d ", obj.val()); }
printf("\n");
// Prints "0 1 2 3 4 "
for (const auto& obj : queue_like) { printf("%d ", obj.val()); }
printf("\n");
將元素插入序列容器
insert
和 insert_after
都會將元素插入
緊接在 (insert
) 之前或緊接在後
(insert_after
) 疊代器。begin()
或 end()
可依
insert
的疊代器,功能等同於
push_front
或 push_back
。如果使用insert_after
未參照元素的疊代器,因此 insert_after
只會
在容器非空白時接受容器的 begin()
,且永遠不得
接受 end()
。延續上一個範例:
queue_like.insert(queue_like.begin(), fbl::MakeRefCounted<Obj>(100));
queue_like.insert(queue_like.end(), fbl::MakeRefCounted<Obj>(500));
for (auto iter = queue_like.begin(), iter != queue_like.end(); ++iter) {
if (iter->val() == 2) {
queue_like.insert(iter, fbl::MakeRefCounted<Obj>(200));
queue_like.insert_after(iter, fbl::MakeRefCounted<Obj>(300));
break;
}
}
// Prints "100 0 1 200 2 300 3 4 500 "
for (const auto& obj : queue_like) { printf("%d ", obj.val()); }
printf("\n");
使用 splice
合併序列容器
最後,splice
會使用指定清單的內容,並將其拼接至
,緊接在另一個清單中的疊代器之前。完成後,
來源清單將是空白的,其所有元素均會移轉至
目的地清單來源清單和目的地清單「必須」不同
而且必須是同一種清單 (例如必須使用相同的清單類型)
節點儲存空間)。begin()
和 end()
是目的地的有效目標
請參考閱讀清單,進一步瞭解
如何選擇 Kubeflow Pipelines SDK 或 TFX前者會在來源至目的地之前將元素加在目的地之前,
後者則會附加為完成前述範例:
TaggedDoublyLinkedList<fbl::RefPtr<Obj>, Tag2> tmp;
tmp.push_front(fbl::MakeRefCounted<Obj>(-1));
tmp.push_front(fbl::MakeRefCounted<Obj>(-2));
queue_like.splice(queue_like.begin(), tmp);
tmp.push_back(fbl::MakeRefCounted<Obj>(1000));
tmp.push_back(fbl::MakeRefCounted<Obj>(2000));
queue_like.splice(queue_like.end(), tmp);
tmp.push_back(fbl::MakeRefCounted<Obj>(50));
tmp.push_back(fbl::MakeRefCounted<Obj>(60));
for (auto iter = queue_like.begin(), iter != queue_like.end(); ++iter) {
if (iter->val() == 300) {
queue_like.splice(iter, tmp);
break;
}
}
// Prints "-2 -1 100 0 1 200 2 50 60 300 3 4 500 1000 2000 "
for (const auto& obj : queue_like) { printf("%d ", obj.val()); }
printf("\n");
從排序容器中移除元素
SinglyLinkedList
提供三種從容器移除元素的方法。
如下所示:
pop_front()
erase_next(Iter)
clear()
DoublyLinkedList
也支援這些方法,但也新增下列內容
方法。
pop_back(Ptr)
erase(Iter or Obj&)
除了 clear()
以外,所有這些方法都會傳回
將容器的指標類型傳回給使用者
物件 (當使用代管指標時) 提供給使用者。活動
指定位置沒有任何元素,就會傳回 nullptr
。這種情況下,erase_next
會傳送無效值
iterator。疊代器必須參照容器中的至少一個元素。
最後,清除作業適用於 元素的疊代器
是清單的成員,或具有物件本身的 T&
樣式參照。
不必透過疊代器找到物件
已清除。
延續上一節中的範例:
// Remove the object with val "-2" and hold a reference to it in |removed|.
auto removed = queue_like.pop_front();
// Remove the object with val "2000" and drop the reference, allowing the object
// to destruct.
queue_like.pop_back();
// Begin refers to the "-1" element, so erase_next will remove the "100" element
queue_like.erase_next(queue_like.begin());
// remove all of the elements in the list that are not in ascending order,
// relative to the previous element. Hold a reference to element 200 as we pass
// it.
fbl::RefPtr<Obj> e200;
for (auto iter = queue_like.begin(); iter.IsValid(); ) {
auto tmp = iter++;
if (iter->IsValid() && (tmp->val() > iter->val())) {
queue_like.erase(iter);
iter = tmp;
} else if (tmp->val() == 200) {
e200 = tmp.CopyPointer();
}
}
// List is now "-1 0 1 200 300 500 1000". Remove 200 from the list using the
// object reference we held instead of an iterator.
queue_like.erase(*e200);
// Finally, just clear the list.
queue_like.clear();