为什么不是容器移动赋值运算符noexcept? [英] Why aren't container move assignment operators 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
istrue
, dumps resources, move assigns allocators, and transfers resources fromc
.
如果
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:
-
当
alloc_traits :: propagate_on_container_move_assignment :: value
true
可以指定移动赋值操作符noexcept
,因为它所有的都是释放当前资源,然后pilfer资源从源头。在这种情况下,分配器也必须被移动赋值,并且移动赋值必须为noexcept
,容器的移动赋值为noexcept
。
When
alloc_traits::propagate_on_container_move_assignment::value
istrue
the move assignment operator can be specifiednoexcept
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 benoexcept
for the container's move assignment to benoexcept
.
当 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屋!