【问题标题】:Why don't iterators depend on allocators? (i.e. does't making iterators SCARY violate the allocator's typedef abstractions?)为什么迭代器不依赖分配器? (即,使迭代器 SCARY 不违反分配器的 typedef 抽象吗?)
【发布时间】:2013-11-13 03:20:00
【问题描述】:

在阅读 C++11 中的 SCARY 迭代器时,I see

从编译器的角度来看,这里没有错。然而,从实际的角度来看,列表迭代器和列表分配器之间没有任何语义依赖性。而且,一般而言,对于所有 STL 容器,迭代器仅取决于(语义上)容器元素类型

不过有一点我不明白:

operator *operator-> 应用于迭代器时,迭代器返回referencepointer 类型。 referencepointerdifference_type等都是从allocator中的typedefs派生而来的。

但分配器不一定必须将pointer定义为value_type *(或者甚至将difference_type定义为ptrdiff_t),例如。

迭代器(一个 SCARY 迭代器)如何在不知道分配器的情况下知道要返回的数据类型?

迭代器是否天生就依赖于它们的这些类型定义的分配器?

【问题讨论】:

  • 为什么pointervalue_type 是从分配器而不是模板参数本身派生的?你没有向后依赖吗?
  • @MarkRansom:你指的是哪个模板参数本身?数据类型T?
  • 是的,抱歉我的评论含糊不清。
  • @MarkRansom: vector::pointer 派生自 allocator::pointer,这意味着 VectorIterator::pointer 必须派生自 vector::pointer,或者换句话说,间接派生自 allocator::pointer。我不认为所有分配器都需要pointervalue_type *。否则 typedef 将完全没有意义(没有双关语)。
  • @Mehrdad:目前大多数分配器对于这些类型都有相同的 typedef(分配器甚至不需要提供类型,因为allocator_traits 中有一个默认值)。在这种情况下,迭代器类型可以相同。

标签: c++ c++11 stl iterator


【解决方案1】:

分配器最初的设计目的是为程序正在编译的平台的内存模型提供一个接口。大多数当前架构(如果不是全部)都提供了平面内存模型,并且单个指针类型可用于在任何程序中寻址内存(不再需要近指针和远指针)。

这反映在allocator_traits 的 C++11 中。现在,分配器不再强制提供许多以前需要的 typedef,包括 pointer_typereference_typedifference_type 等,因为存在已知的良好默认值。这确实符合当前的实践,在大多数 STL 实现中,这些类型在所有分配器中都是相同的。

每当分配器不提供 typedef 或类型与allocator_traits 中提供的默认值相同时,根据用于构造容器的分配器来区分迭代器是没有意义的。如果该假设不成立,则实现可以确定为那些提供不同于默认类型定义集的分配器使用不同的迭代器类型。

请注意,我没有查看它们的实现,因此请从表面上看:这将支持预期目的(在不破坏标准合规性的情况下最小化生成的代码)。

另请注意,这不是唯一的方法。 C++11 中的当前分配器模型支持使用多态分配器,即使标准还没有提供实现。使用polymorphic allocators,单个分配器模板参数(多态适配器)提供类型定义和与容器的接口,在内部管理指向用于提供内存的实际分配器的指针。

多态分配器的目的与链接文章中提到的论文相同:允许创建词汇类型SCARY 分配器专注于为特定容器类型的迭代提供词汇类型,多态分配器更进一步,允许将容器本身用作词汇类型,而不管实际的获取内存的机制是。

您可以在 Bloomberg 的 BSL 中找到多态分配器的参考实现(使用不同的名称)

【讨论】:

  • 哦... SCARY 迭代器是“可选”的东西吗?我的印象是,vector 之类的类型必须具有 SCARY 迭代器……如果没有,那将回答我的问题。
  • @Mehrdad:我真的不知道,但如果你需要遵守标准,你必须遵守语言规则。如果您有权访问该工具链,您可能可以对此进行测试。创建一个分配器,定义不同的pointer_typereference_type……然后比较std::vector<int>::iteratorstd::vector<int,yourallocator>::iterator的类型是否完全相同。
  • @Mehrdad:不,不需要 SCARY 迭代器。我认为他们是推荐的,但仅此而已。
  • @Xeo:很有趣。他们不是总是可选的吗?你应该如何在你的代码中使用它们? (这是否意味着它们不可携带?)
  • @Mehrdad:是的,它们本质上是不可移植的,因为它们不是必需的——你必须查阅你的实现文档(MSVC 有它们)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-02-05
  • 1970-01-01
  • 2016-09-23
  • 2013-11-02
  • 2021-02-11
  • 2019-04-06
相关资源
最近更新 更多