Fil*_*efp 13 c++ language-lawyer c++11
注:由Originially问GreenScape的评论.
阅读之后为什么STL容器中的交换成员函数未声明为noexcept?似乎在为标准容器执行时潜在的未定义行为的原因a.swap(b)归结为也交换或不交换底层分配器.
Fil*_*efp 13
让我们开始深入研究标准(N3797):
23.2.1p9一般集装箱要求[container.requirements.general]如果
allocator_traits<allocator_type>::propagate_on_container_swap::value是true,那么也应该使用对非成员的未经授权的呼叫来交换a和的分配器.否则,它们不应被交换,并且行为是未定义的,除非.bswapa.get_allocator() == b.get_allocator()
目的是propagate_on_container_swap什么?
如果一个Allocator有一个名为的typedefpropagate_on_container_swap引用std::true_type了两个被交换的容器的底层分配器,那么它也会交换.[1]
如果propagate_on_container_swap是std::false_type只有两个容器的数据会掉,但是分配器将继续留在自己的位置.
[1]这意味着之后a.swap(b),a.get_allocator()将是以前的b.get_allocator(); 分配器已交换.
有状态分配器的含义是什么?
Allocator不仅负责为标准容器中的元素分配内存,它们还负责释放所述元素.
C++ 03不允许在标准容器中使用有状态分配器,但是C++ 11必须要求支持这样的分配器.这意味着我们可以定义一个分配器,它取决于它的构造方式,以某种方式运行.
如果分配器propagate_on_container_swap::value等于false所涉及的两个分配器之间的状态差异,则可能导致未定义的行为,因为分配器的一个实例可能与另一个实例处理的数据不兼容.
如果没有正确交换有状态分配器可能会出现什么问题?
假设我们有一个MagicAllocator使用malloc或operator new分配内存,具体取决于它的构造方式.
如果它用于malloc分配内存,则必须使用它free来释放它,如果是operator new,delete则需要; 因此,它必须保留一些信息,说明它应该使用哪两个.
如果我们有两个std::vector都使用MagicAllocator但具有不同的状态(意味着一个使用malloc和另一个operator new),并且我们不在分配器上交换a.swap(b)分配器将不匹配在交换后为两个向量中的元素分配的内存 -这就意味着在解除分配时可能会调用错误free/ delete.
| 归档时间: |
|
| 查看次数: |
389 次 |
| 最近记录: |