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

时间:2013-05-03 13:27:14

标签: c++ memory-management c++11 allocator

所以我在查看std::vector的规范,并注意到reference typedef已从C ++ 03中的Allocator::reference更改为C ++ 11中的value_type&。我很惊讶,所以我开始深入了解。

在C ++03§20.1.5[lib.allocator.requirements]中有表32,其中X::reference被定义为T&X::const_reference被定义为{{ 1}}。

但是,在C ++11§17.6.3.5[allocator.requirements]中,表28中缺少T const&reference

接下来,我们在C ++ 11中添加了§20.6.8const_reference,其中不包括std::allocator_traits。但§20.6.9reference确实如此。

最后,有§23.2.1[container.requirements.general],它将std::allocator定义为“X::reference的左值”,T为{{1}的值{{1} }}”。

所以,我用Google搜索并发现这篇文章(12)建议从分配器要求中删除X::const_reference,但它没有提到它背后的任何理由。但也有LWG issue反对改变。

另外,我找到了the interview with Alexander Stepanov,其中他讲述了T如何封装机器特定的内存布局和Herb Sutter's post,其中他谈到了指向容器元素,容器要求和reference不是一个容器。

那么,你怎么看待这一切呢? reference有用吗,是否符合它的目的? “花式”引用如何符合标准?这是一个大胆的举措,以完全消除它们,制定更严格的容器要求并弃用std::vector<bool>

3 个答案:

答案 0 :(得分:5)

因为嵌套的typedef是多余的。 Scott Meyers的有效STL ,第49页:

  

标准明确允许库实现者假设   每个分配器的指针typedef是T *和每个的同义词   allocator的引用typedef与T&amp;

相同

答案 1 :(得分:3)

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

  

“它们最初的目的是使库更灵活,独立于底层内存模型,允许程序员在库中使用自定义指针和引用类型。但是,在将STL引入C ++标准的过程中,C ++标准化委员会意识到内存模型的完全抽象会导致不可接受的性能损失。为了解决这个问题,分配器的要求受到更多的限制。因此,分配器提供的定制水平比原来更有限。斯捷潘诺夫设想。“

最初它们被设计为抽象出内存本身,允许一个人分配内存,另一台机器通过和互联网连接,并使用指针/引用来回复制数据以跟踪什么是生活。同样,可以在纯C ++中创建类似Java的GC。这种抽象似乎是一个了不起的想法!

然而,这导致了当时被认为不可接受的性能处罚。另外,如果你考虑一下,在代码中工作几乎是不可能的。每个void func(const string&)都必须变成template<class allocator> void func(allocator::reference),这是一个不可推导的上下文,所以你必须在函数调用(func<std::allocator<std::string>::const_reference>(username))中明确地编写分配器,没有人会这样做,这会使GC无法正常工作。如今,分配器只是抽象内存分配/释放。

答案 2 :(得分:2)

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

但是,由于原因不明,因为我没有那么多时间去搜索,C ++ 03标准在§20.1.5第4页中有以下文字:

  

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

     

- 给定分配器类型的所有实例都必须是可互换的,并且始终比较等于   彼此。

     

- typedef成员指针,const_pointer,size_type和difference_type是   需要分别为T *,T const *,size_t和ptrdiff_t。

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

在我搜索所有提及“分配器”一词的所有C ++之前的11篇论文时,我找到了一个主要的共识,即从标准中删除这些词。最后,this paper建议使用以下评论删除它们:

  

狡猾的话语已经消失了。举起你的杯子,祝酒。

胜利?我们的记忆模型能否最终消失?没有那么多。除其他事项外,同一篇论文建议从分配器要求中删除reference。它看起来像是投入了标准。

我之前提到的LWG issue反对这一改变,但它以下列声明结束:

  

未做出改变的共识

所以看起来分配器的最初目的在今天并不那么重要。以下是Wikipedia所说的内容:

  

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

最后,Container::reference与分配器无关。它的创建是为了允许代理集合which are not actually containers。所以它就在这里。顺便说一下,它似乎是标准中最终单词如何违背原始意图的另一个例子。