考虑到复制构造的要求,如何在 C++11 中编写有状态分配器?
据我所知,与 STL 一起使用的分配器的要求容器在 C++11 标准第 17.6.3.5 节的表 28 中列出.
As far as I can tell, the requirements on an allocator to be used with STL containers are laid out in Table 28 of section 17.6.3.5 of the C++11 standard.
我对其中一些要求之间的相互作用有些困惑.给定类型 X
是类型 T
的分配器,类型 Y
是类型U
、实例a
、a1
和a2
的相应分配器类"X
,以及一个Y
的实例b
,表格中写着:
I'm a bit confused about the interaction between some of these requirements.
Given a type X
that is an allocator for type T
, a type Y
that is "the
corresponding allocator class" for type U
, instances a
, a1
, and a2
of
X
, and an instance b
of Y
, the table says:
表达式
a1 == a2
仅在分配了存储空间时计算为true
a1
可以被a2
释放,反之亦然.
The expression
a1 == a2
evaluates totrue
only if storage allocated froma1
can be deallocated bya2
, and vice versa.
表达式 X a1(a);
格式良好,不会通过异常退出,然后 a1 == a
为真.
The expression X a1(a);
is well-formed, doesn't exit via an exception,
and afterward a1 == a
is true.
表达式 X a(b)
格式良好,不会通过异常退出,并且之后a == b
.
The expression X a(b)
is well-formed, doesn't exit via an exception, and
afterward a == b
.
我读这句话是说所有分配器在这样的情况下都必须是可复制构造的副本与原件互换的方式.更糟糕的是,同样的跨类型边界为真.这似乎是一个相当繁重的要求;作为据我所知,这使得大量类型的分配器变得不可能.
I read this as saying that all allocators must be copy-constructible in such a way that the copies are interchangeable with the originals. Worse, the same true across type boundaries. This seems to be a pretty onerous requirement; as far as I can tell, it makes impossible a large number of types of allocators.
例如,假设我有一个要在我的分配器中使用的 freelist 类,为了缓存释放的对象.除非我遗漏了什么,否则我不能在分配器中包含该类的实例,因为大小或T
和 U
的对齐方式可能不同,因此空闲列表条目是不兼容.
For example, say I had a freelist class that I wanted to use in my allocator,
in order to cache freed objects. Unless I'm missing something, I couldn't
include an instance of that class in the allocator, because the sizes or
alignments of T
and U
might differ and therefore the freelist entries are
not compatible.
我的问题:
我上面的解释正确吗?
Are my interpretations above correct?
我在几个地方读到 C++11 改进了对有状态的分配器".鉴于这些限制,情况如何?
I've read in a few places that C++11 improved support for "stateful allocators". How is that the case, given these restrictions?
你对如何做我想做的事情有什么建议吗做?也就是说,我如何在我的分配器中包含分配类型特定的状态?
Do you have any suggestions for how to do the sort of thing I'm trying to do? That is, how do I include allocated-type-specific state in my allocator?
总的来说,分配器的语言似乎很草率.(例如,表 28 的序言说假设 a
是 X&
类型,但是一些表达式重新定义 a
.)此外,至少 GCC 的支持是不一致的.是什么解释了分配器的这种奇怪之处?难道只是偶尔使用的功能?
In general, the language around allocators seems sloppy. (For example, the
prologue to Table 28 says to assume that a
is of type X&
, but some of the
expressions redefine a
.) Also, at least GCC's support is non-conformant.
What accounts for this weirdness around allocators? Is it just an infrequently
used feature?
推荐答案
1) 我上面的解释正确吗?
1) Are my interpretations above correct?
您是对的,您的空闲列表可能不适合分配器,它需要能够处理多种大小(和对齐方式)以适应.这是free-list要解决的问题.
You are right that your free-list might not be a good fit for allocators, it need be able to handle multiple sizes (and alignments) to fit. That's a problem for the free-list to solve.
2) 我在一些地方读到 C++11 改进了对有状态分配器"的支持.鉴于这些限制,情况如何?
2) I've read in a few places that C++11 improved support for "stateful allocators". How is that the case, given these restrictions?
它并没有比出生改善多少.在 C++03 中,该标准只是推动实现者提供可以支持非平等实例和实现者的分配器,有效地使有状态分配器不可移植.
It is not so much improved, than born. In C++03 the standard only nudged implementers toward providing allocators which could support non-equal instances and implementers, effectively making stateful allocators non-portable.
3) 对于如何做我正在尝试做的事情,您有什么建议吗?也就是说,我如何在我的分配器中包含分配类型特定的状态?
3) Do you have any suggestions for how to do the sort of thing I'm trying to do? That is, how do I include allocated-type-specific state in my allocator?
您的分配器可能必须灵活,因为您不应该确切知道它应该分配什么内存(和什么类型).此要求对于将您(用户)与使用分配器的某些容器(例如 std::list
、std::set
或 std::set
或<代码>std::map.
Your allocator may have to be flexible, because you are not supposed to know exactly what memory (and what types) it is supposed to allocate. This requirement is necessary to insulate you (the user) from the internals of some of the container that uses the allocator such as std::list
, std::set
or std::map
.
您仍然可以将此类分配器与诸如 std::vector
或 std::deque
之类的简单容器一起使用.
You can still use such allocators with simple containers such as std::vector
or std::deque
.
是的,这是一项代价高昂的要求.
Yes, it is a costly requirement.
4) 一般来说,关于分配器的语言似乎很草率.(例如,表 28 的序言说假设 a 是 X& 类型,但有些表达式重新定义了 a.)此外,至少 GCC 的支持是不符合的.是什么解释了分配器的这种奇怪之处?它只是一个不常用的功能吗?
4) In general, the language around allocators seems sloppy. (For example, the prologue to Table 28 says to assume that a is of type X&, but some of the expressions redefine a.) Also, at least GCC's support is non-conformant. What accounts for this weirdness around allocators? Is it just an infrequently used feature?
一般来说,标准并不容易阅读,不仅仅是分配器.你必须小心.
The Standard in general is not exactly easy to read, not only allocators. You do have to be careful.
为了学究,gcc 不支持分配器(它是一个编译器).我猜你说的是 libstdc++(gcc 附带的标准库实现).libstdc++ 是旧,因此它是为 C++03 量身定做的.它已针对 C++11 进行了调整,但尚未完全符合(例如,仍对字符串使用 Copy-On-Write).原因是 libstdc++ 非常注重二进制兼容性,而 C++11 要求的一些更改会破坏这种兼容性;因此,必须仔细介绍它们.
To be pedant, gcc does not support allocators (it's a compiler). I surmise that you are speaking about libstdc++ (the Standard Library implementation shipped with gcc). libstdc++ is old, and thus it was tailored to C++03. It has been adapted toward C++11, but is not fully conformant yet (still uses Copy-On-Write for strings, for example). The reason is that libstdc++ has a huge focus on binary compatibility, and a number of changes required by C++11 would break this compatibility; they must therefore be introduced carefully.
相关文章