Why does reallocating a vector copy instead of moving the elements? [duplicate]

房东的猫 提交于 2019-11-27 08:00:00

The short answer is that I think @BenVoigt is basically correct.

In the description of reserve (§23.3.6.3/2), it says:

If an exception is thrown other than by the move constructor of a non-CopyInsertable type, there are no effects.

[And the description of resize in §23.3.6.3/12 requires the same.]

This means that if T is CopyInsertable, you get strong exception safety. To assure that, it can only use move construction if it deduces (by unspecified means) that move construction will never throw. There's no guarantee that either throw() or noexcept will be necessary or sufficient for that though. If T is CopyInsertable, it can simply choose to always use copy construction. Basically, what's happening is that the standard requires copy construction-like semantics; the compiler can only use move construction under the as-if rule, and it's free to define when or if it'll exercise that option.

If T is not CopyInsertable, reallocation will use move construction, but exception safety depends on whether T's move constructor can throw. If it doesn't throw, you get strong exception safety, but if it throws, you don't (I think you probably get the basic guarantee, but maybe not even that and definitely no more).

Ben Voigt

It's not a regression, it's a bug fix. The standard specifies that std::vector will only prefer an element move constructor which is non-throwing.

See also this explanation and this bug report.

This question is also relevant.

Tip-of-trunk clang + libc++ gets:

foo(1)
foo(2)
foo(move(foo(1))
~foo(2)
~foo(1)

If you remove the noexcept from the move constructor, then you get the copy solution:

foo(1)
foo(2)
foo(foo(1))
~foo(1)
~foo(2)
~foo(1)
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!