Fil*_*efp 11 c++ allocator language-lawyer c++11
注:最初由问马特·麦克纳布的评论上为什么能交换标准库容器在C++ 11(包括分配器)是有问题的?.
标准(N3797)说,如果progagate_on_container_swap内部分配器是std::false_type它会产生不确定的行为,如果涉及的两个分配器不比较平等的.
23.2.1p9一般集装箱要求[container.requirements.general]如果
allocator_traits<allocator_type>::propagate_on_container_swap::value是true,那么也应该使用对非成员的未经授权的呼叫来交换a和的分配器.否则,它们不应被交换,并且行为是未定义的,除非.bswapa.get_allocator() == b.get_allocator()
Fil*_*efp 10
我可以想到一些现实生活中的场景,其中标准所允许的构造既有意义,又是必需的; 我将首先尝试从更广泛的角度回答这个问题,而不是涉及任何具体问题.
说明
分配器 是负责分配,构造,破坏和解除分配内存和实体的神奇事物.由于C++ 11 有状态分配器 发挥作用,分配器可以比以前做得更多,但这一切都归结为前面提到的四个操作.
分配器具有的要求载荷,其中之一是该a1 == a2(其中a1和a2是相同的类型的分配器)必须产生true 仅如果内存分配由一个可被解除分配由另一[1] .
上述要求operator==意味着两个分配器比较相等可以做不同的事情,只要它们仍然可以相互理解内存的分配方式.
以上是标准允许propagate_on_container_*等于的原因std::false_type; 我们可能想要更改两个容器的内容,其中分配器具有相同的释放行为,但保留其他行为(与基本内存管理无关).
[1]如[allocator.requirements]p2(表28)所述
(SILLY)故事
想象一下,我们有一个名为Watericator的分配器,它根据请求的分配收集水,并将其交给所请求的容器.
Watericator是一个有状态的分配器,在构建我们的实例时我们可以选择两种模式;
聘请埃里克,他在淡水泉水中取水,同时还测量(并报告)水位和纯度.
聘请亚当,他在后院使用水龙头,并不关心伐木.亚当是不是快了很多埃里克.
无论水来自哪里,我们总是以同样的方式处理它; 浇水我们的植物.即使我们有一个实例,埃里克正在为我们提供水(记忆),另一个Adam实际使用水龙头,两个水刀都比较平等operator==.
一个人完成的分配可以由另一个人解除分配.
上面可能是一个愚蠢的比喻,但想象一下我们有一个分配器可以记录每个分配,我们在我们的代码中的某个容器上使用它,这对我们感兴趣; 我们后来想把元素从这个容器移到另一个容器中......但我们不再对所有的日志记录感兴趣.
如果没有有状态分配器,并且propagate_on_container_*关闭选项,我们将被迫1)复制所涉及的每个元素2)坚持使用(不再需要)日志记录.
| 归档时间: |
|
| 查看次数: |
500 次 |
| 最近记录: |