为什么不是容器移动赋值运算符noexcept? [英] Why aren't container move assignment operators noexcept?

查看:179
本文介绍了为什么不是容器移动赋值运算符noexcept?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我注意到, std :: string 的(真的 std :: basic_string 的)是 noexcept 。这对我有意义。但是我注意到没有一个标准容器(例如, std :: vector std :: deque code> std :: list , std :: map )声明其移动赋值操作符 noexcept 。这对我来说没有意义。例如, std :: vector 通常实现为三个指针,并且指针可以被移动分配而不抛出异常。然后我认为也许问题是移动容器的分配器,但 std :: string '也有分配器,所以如果这是问题,我期望它会影响 std :: string

I noticed that std::string's (really std::basic_string's) move assignment operator is noexcept. That makes sense to me. But then I noticed that none of the standard containers (e.g., std::vector, std::deque, std::list, std::map) declares its move assignment operator noexcept. That makes less sense to me. A std::vector, for example, is typically implemented as three pointers, and pointers can certainly be move-assigned without throwing an exception. Then I thought that maybe the problem is with moving the container's allocator, but std::string's have allocators, too, so if that were the issue, I'd expect it to affect std::string.

那么为什么 std :: string 的移动赋值运算符 noexcept ,但是标准容器的移动赋值运算符不是?

So why is std::string's move assignment operator noexcept, yet the move assignment operators for the standard containers are not?

推荐答案

我相信我们正在看一个标准缺陷。 noexcept 规范,如果要应用于移动赋值运算符,则有些复杂。我相信这个说法是真的,无论我们是在谈论 basic_string 还是向量

I believe we're looking at a standards defect. The noexcept specification, if it is to be applied to the move assignment operator, is somewhat complicated. And I believe this statement to be true whether we are talking about basic_string or vector.

根据[container.requirements.general] / p7,容器移动赋值运算符应该做什么的英语翻译是:

Based on [container.requirements.general]/p7 my English translation of what a container move assignment operator is supposed to do is:

C& operator=(C&& c)




如果 alloc_traits :: propagate_on_container_move_assignment :: value
true ,转储​​资源,移动分配分配器和传输
资源 c

If alloc_traits::propagate_on_container_move_assignment::value is true, dumps resources, move assigns allocators, and transfers resources from c.

如果
alloc_traits :: propagate_on_container_move_assignment :: value false
get_allocator()== c.get_allocator()转储资源,并从 c 转移资源

If alloc_traits::propagate_on_container_move_assignment::value is false and get_allocator() == c.get_allocator(), dumps resources, and transfers resources from c.

如果
alloc_traits :: propagate_on_container_move_assignment :: value false
get_allocator()!= c.get_allocator (),move指定每个 c [i]

If alloc_traits::propagate_on_container_move_assignment::value is false and get_allocator() != c.get_allocator(), move assigns each c[i].


$ b b

注意:

Notes:


  1. alloc_traits :: propagate_on_container_move_assignment :: value true 可以指定移动赋值操作符 noexcept ,因为它所有的都是释放当前资源,然后pilfer资源从源头。在这种情况下,分配器也必须被移动赋值,并且移动赋值必须为 noexcept ,容器的移动赋值为 noexcept

  1. When alloc_traits::propagate_on_container_move_assignment::value is true the move assignment operator can be specified noexcept because all it is going to is deallocate current resources and then pilfer resources from the source. Also in this case, the allocator must also be move assigned, and that move assignment must be noexcept for the container's move assignment to be noexcept.

alloc_traits :: propagate_on_container_move_assignment :: value false ,如果两个分配器相等,那么它将做与#1相同的事情。但是,不知道分配器在运行时间之前是否相等,因此您不能将 noexcept 作为基础。

When alloc_traits::propagate_on_container_move_assignment::value is false, and if the two allocators are equal, then it is going to do the same thing as #1. However one doesn't know if the allocators are equal until run time, so you can't base noexcept on this possibility.

alloc_traits :: propagate_on_container_move_assignment :: value false 时,如果两个分配器等于,则必须移动分配每个单独的元素。这可能涉及向目标添加容量或节点,因此本质上 noexcept(false)

When alloc_traits::propagate_on_container_move_assignment::value is false, and if the two allocators are not equal, then one has to move assign each individual element. This may involve adding capacity or nodes to the target, and thus is intrinsically noexcept(false).

总结:

C& operator=(C&& c)
        noexcept(
             allocator_type::propagate_on_container_move_assignment::value &&
             is_nothrow_move_assignable<allocator_type>::value);

我看不到依赖 C :: value_type 在上面的规范,所以我相信它应该同样适用于 std :: basic_string 尽管C ++ 11指定否则。

And I see no dependence on C::value_type in the above spec and so I believe it should apply equally well to std::basic_string despite C++11 specifying otherwise.

这篇关于为什么不是容器移动赋值运算符noexcept?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆