为什么Allocator::reference被逐步淘汰

Why is Allocator::reference being phased out?

本文关键字:淘汰 reference Allocator 为什么      更新时间:2023-10-16

所以我正在查看std::vector的规范,并注意到reference的类型定义从c++ 03中的Allocator::reference变为c++ 11中的value_type&。我很惊讶,所以我开始深入调查。

在c++ 03§20.1.5中[lib.allocator.]在表32中,X::reference被定义为T&, X::const_reference被定义为T const&

然而,在c++ 11§17.6.3.5中[allocator.]表28中缺少referenceconst_reference

接下来,我们在c++ 11中添加了§20.6.8 std::allocator_traits,其中不包括reference。但是§20.6.9 std::allocator可以。

最后是§23.2.1 [container.requirements]。其中定义X::reference为"T的左值",X::const_reference为"T的const左值"。

所以,我在谷歌上找到了这篇论文(1,2),它建议从分配器需求中删除reference,但它没有提到它背后的任何理由。但是也有一个LWG的问题反对这一改变。

此外,我还发现了Alexander Stepanov的采访,他谈到了reference如何封装特定于机器的内存布局,以及Herb Sutter的帖子,他谈到了容器元素的指针,容器需求以及std::vector<bool>如何不是容器。

那么,你怎么看这一切?reference有用吗?它达到目的了吗?"花哨"的引用如何符合标准?这是一个大胆的举动,完全消除它们,使更严格的容器要求和弃用std::vector<bool>吗?

因为嵌套的类型定义是多余的。Scott Meyers的Effective STL,第49页:

标准明确地允许库实现者这样假设每个分配器的指针类型是T*和every的同义词allocator的引用类型定义与T&

相同。

http://en.wikipedia.org/wiki/Allocator_ (C % 2 b % 2 b)

它们最初的目的是使库更灵活,独立于底层内存模型,允许程序员在库中使用自定义指针和引用类型。然而,在将STL纳入c++标准的过程中,c++标准化委员会意识到,对内存模型的完全抽象将导致无法接受的性能损失。为了解决这个问题,对分配器的要求进行了更严格的限制。因此,分配器提供的定制级别比Stepanov最初设想的要有限得多。"

最初,它们被设计为抽象出内存本身,允许一个人通过互联网连接在另一台机器上分配内存,并使用指针/引用来回复制数据以跟踪实时情况。类似地,可以在纯c++中创建类似java的GC。这种抽象似乎是一个惊人的想法!

但是,这会导致性能损失,这在当时被认为是不可接受的。而且,如果你仔细想想,用代码工作几乎是不可能的。每个void func(const string&)都必须变成template<class allocator> void func(allocator::reference),这是一个不可推导的上下文,因此您必须在函数调用(func<std::allocator<std::string>::const_reference>(username))中显式地编写分配器,没有人会这样做,这会使GC无法正常工作。现在,分配器仅仅抽象了内存分配/释放。

在对Alexander Stepanov的采访中,他提到在将STL添加到标准库的提议中,他被要求创建一个内存模型的抽象。因此,分配器诞生了。在LWG问题中有一个实现示例,其中自定义分配器的reference被定义为T __far&

但是,由于未知的原因,因为我没有那么多的时间来搜索,c++ 03标准在§20.1.5 p4中有以下文本:

本国际标准中描述的容器的实现允许假设它们的Allocator模板形参满足表32之外的以下两个附加要求。

-给定分配器类型的所有实例都必须是可互换的,并且总是比较相等对方。

- typepedef成员指针、const_pointer、size_type和difference_type是要求分别为T*、T const*、size_t和ptrdiff_t。

这有效地破坏了自定义内存模型分配器与标准容器互操作的能力。

在我搜索所有提到"分配器"一词的c++ 11之前的论文时,我发现了一个主要的共识,即从标准中删除这些词。最后,本文建议通过以下注释来删除它们:

黄鼠狼的话不见了。举起你的酒杯,干杯。

胜利?我们的记忆模型终于可以疯狂了吗?没有那么多。除此之外,同一篇论文还建议将reference从分配器需求中删除。而且看起来它已经被选为标准了。

我之前提到的LWG问题反对更改,但它以以下声明结束:

没有一致意见做出改变

所以看起来分配器最初的目的在今天不那么重要了。维基百科是这么说的:

分配器当前的目的是让程序员控制容器内的内存分配,而不是适应底层硬件的地址模型。事实上,修订后的标准消除了分配器表示c++地址模型扩展的能力,正式地(并且故意地)消除了它们的原始目的。

最后,Container::reference与分配器无关。它的创建是为了允许实际上不是容器的代理集合。所以它就留在这里了。顺便说一下,这似乎是标准中结束语违背初衷的又一个例子。

相关文章: