size() 的操作顺序

常量顺序与线性顺序 size()

std:: 容器不同,并非所有 fbl:: 容器都会自动跟踪容器的特定大小。具体而言,关联容器始终跟踪容器中的元素数量,而有序容器默认不会跟踪。

为了避免在容器上遇到对 size() 方法的意外 O(n) 调用时出现任何意外情况,有序容器的 API 不包含 size() 方法。更准确地说,尝试调用 size() 将会触发 static_assert 并且无法编译。

相反,如果需要知道当前有序容器中的特定元素数量,并且元素的 O(n) 数量是可接受的支付价格,则可以调用 size_slow()

另一方面,如果需要在有序容器中实现 O(1) 性能,用户可以改用“有尺寸”的容器版本。容器的内存中大小将增加一个 size_t,向容器添加/从容器中移除元素需要支付的保持容器中元素数量的费用稍高一些。现在允许调用 size(),调用 size_slow() 现在会变为错误。

指定列表应自动跟踪其大小的简单方法是在声明容器时使用 SizedSinglyLinkedListSizedDoublyLinkedList 模板别名。或者,您也可以通过将 fbl::SizeOrder::Constant 或 fbl::SizeOrder::N 传递到模板参数中的相应位置手动指定模板参数。

所有 fbl:: 容器都支持低成本的 O(1) is_empty() 操作,该操作可用于简单地测试容器是否存储任何元素。

// This is a list with an O(n) size_slow method
fbl::SinglyLinkedList<std::unique_ptr<Obj>> my_stack;
if (my_stack.size() > 50) { /* ... */ }       // not allowed. Compile time error
if (my_stack.size_slow() > 50) { /* ... */ }  // allowed.
if (my_stack.is_empty()) { /* ... */ }        // always allowed.

// This is a list with an O(1) size method
fbl::SizedSinglyLinkedList<std::unique_ptr<Obj>> my_sized_stack;
if (my_sized_stack.size() > 50) { /* ... */ }      // allowed.
if (my_sized_stack.size_slow() > 50) { /* ... */ } // not allowed. Compile time error
if (my_sized_stack.is_empty()) { /* ... */ }       // always allowed.

// A more verbose way to say the same thing
fbl::SinglyLinkedList<std::unique_ptr<Obj>,
                      fbl::DefaultObjectTag,
                      fbl::SizeOrder::Constant> another_sized_stack;
if (another_sized_stack.size() > 50) { /* ... */ }      // allowed.
if (another_sized_stack.size_slow() > 50) { /* ... */ } // not allowed. Compile time error
if (another_sized_stack.is_empty()) { /* ... */ }       // always allowed.

// Both of these work as well.
struct Tag1 {};
struct Tag2 {};
fbl::SinglyLinkedList<std::unique_ptr<Obj>, Tag1,
                      fbl::SizeOrder::Constant> t1_sized_stack;
fbl::TaggedSinglyLinkedList<std::unique_ptr<Obj>, Tag2,
                      fbl::SizeOrder::Constant> t2_sized_stack;
if (t1_sized_stack.size() > 50) { /* ... */ }      // allowed.
if (t2_sized_stack.size() > 50) { /* ... */ }      // allowed.
if (t1_sized_stack.size_slow() > 50) { /* ... */ } // not allowed. Compile time error
if (t2_sized_stack.size_slow() > 50) { /* ... */ } // not allowed. Compile time error