为何std::vector的swap函数noexcept规格与其他容器不同?
为什么std::vector的swap noexcept规格和其他容器不一样?
核心原因得从vector的swap实现逻辑和标准的异常安全设计说起:
vector的swap本质就是换三个指针
vector内部靠三个指针管理内存:起始地址、已用区域末尾、容量末尾。swap的时候就是直接交换这三个指针,这个操作本身绝对不会抛异常,完全是noexcept的。分配器交换的异常保证有区别
当需要交换两个容器的分配器时(也就是std::allocator_traits<Allocator>::propagate_on_container_swap为true的情况):- 对vector来说,分配器的交换操作被标准确保是
noexcept的——要么分配器自己提供了不会抛异常的swap成员函数,要么分配器是is_always_equal类型(这种情况下根本不用实际交换分配器)。所以只要propagate_on_container_swap为真,分配器交换不会带来异常风险。 - 对list、map这类容器来说,它们的内部结构依赖分配器管理节点内存,交换分配器的操作没办法被标准统一保证不抛异常。因此标准只在分配器是
is_always_equal(不用交换分配器)的时候,才要求它们的swap是noexcept的。
- 对vector来说,分配器的交换操作被标准确保是
合法swap的前提要注意
不管哪种容器,要是两个容器的分配器不相等,同时propagate_on_container_swap又是false,那swap的行为是未定义的。但vector在合法的swap场景里(分配器相等,或者propagate_on_container_swap为真),核心的指针交换加上分配器交换都能保证不抛异常,所以标准给它开了特例,制定了更宽松的noexcept规格。
内容的提问来源于stack exchange,提问作者LoS
相关产品推荐
相关产品推荐

