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

Lyb*_*rta 26 c++ memory-management allocator c++11

所以我在查看规范std::vector并注意到referencetypedef从Allocator::referenceC++ 03变为value_type&C++ 11.我很惊讶,所以我开始深入了解.

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

然而,在C++ 11§17.6.3.5[allocator.requirements]有表28中,referenceconst_reference缺失.

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

最后,有§23.2.1[container.requirements.general]定义X::reference为"左值T"并且X::const_reference是"const左值T".

所以,我用Google搜索,发现这个文件(1,2)该提议移除reference从分配器的要求,但它并没有提到它后面的任何理由.但也有一个LWG问题反对这一变化.

此外,我找到了亚历山大·斯捷潘诺夫的访谈,其中他谈到了如何reference封装机器特定的内存布局和Herb Sutter的帖子,其中他谈到了指向容器元素,容器要求以及如何std::vector<bool>不是容器的指针.

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

Sco*_*nes 5

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

标准明确允许库实现者假设每个分配器的指针typedef是T*的同义词,并且每个分配器的引用typedef与T&相同


Moo*_*uck 5

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

“它们最初的目的是使库更加灵活并独立于底层内存模型,允许程序员在库中使用自定义指针和引用类型。然而,在将 STL 纳入 C++ 标准的过程中,C++标准化委员会意识到内存模型的完全抽象会导致不可接受的性能损失。为了弥补这一点,分配器的要求变得更加严格。因此,分配器提供的定制级别比 Stepanov 最初设想的更有限.”

最初,它们旨在抽象出内存本身,允许一个人通过互联网连接在另一台机器上分配内存,并使用指针/引用来回复制数据以跟踪实时数据。类似地,可以用纯 C++ 进行类似 Java 的 GC。这种抽象似乎是一个了不起的想法!

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


小智 2

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

\n\n

但是,由于未知的原因,因为我没有那么多时间进行搜索,C++03 标准在 \xc2\xa720.1.5 p4 中有以下文本:

\n\n
\n

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

\n\n

\xe2\x80\x94 给定分配器类型的所有实例都需要可互换,并且彼此比较时始终相等。

\n\n

\xe2\x80\x94 typedef 成员pointer、const_pointer、size_type 和difference_type 需要分别为T*、T const*、size_t 和ptrdiff_t。

\n
\n\n

这实际上削弱了自定义内存模型分配器与标准容器互操作的能力。

\n\n

在我搜索所有提到“分配器”一词的 C++11 之前的论文期间,我发现了一个主要共识,即从标准中删除这些词。最后,这篇论文建议删除它们,并附有以下评论:

\n\n
\n

黄鼠狼的话消失了。举起酒杯,干杯。

\n
\n\n

胜利?我们最终可以对我们的记忆模型进行疯狂吗?没有那么多。除其他外,同一篇论文建议删除reference分配器要求。看起来它已被投票纳入标准。

\n\n

LWG问题这一更改,但它以以下声明结束:

\n\n
\n

没有达成共识来做出改变

\n
\n\n

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

\n\n
\n

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

\n
\n\n

最后,Container::reference与分配器无关。它的创建是为了允许代理集合,但实际上并不是容器。所以它会一直存在。顺便说一句,这似乎是标准中最后一句话与初衷背道而驰的又一个例子。

\n