4

Are std::vector required to use move instead of copy, at reallocation on grow/swap/erase by standard? Or this is purely implementation optimization?

If std::vector required to use move, at what conditions? Where these rules/conditions can be read?

I found this How to enforce move semantics when a vector grows? . But there are no answers about guarantees.

UPDATE

When it required to use move constructor on reallocation? And where it says that it required to reallocate with move semantic?

tower120
  • 5,007
  • 6
  • 40
  • 88
  • 2
    The Standard is clear about all this, but if you insist on cliff notes: duplicate of [Why does std::vector require move-constructors for its elements?](https://stackoverflow.com/questions/30114291/why-does-stdvector-require-move-constructors-for-its-elements) (read: _When_) – underscore_d Oct 30 '17 at 14:24
  • 1
    Too broad. Required to use a move **when**? There are instances where it will move, and instances where it will copy. Also, **what** should be moved? The individual elements? The vectors own buffer pointer? – StoryTeller - Unslander Monica Oct 30 '17 at 14:30
  • I'm interesting in all reallocation/swap cases. Like `emplace_back(T&&)`/`insert(T&&)`/`erase`/`swap`. I'm not asking about explicit vector copy, like `vec1 = vec2`. – tower120 Oct 30 '17 at 14:39
  • *All* cases? Then I re-iterate. Too broad. – StoryTeller - Unslander Monica Oct 30 '17 at 15:18
  • @StoryTeller consider "reallocation caused by emplace_back(T&&)" :) – tower120 Oct 30 '17 at 15:19
  • 1
    @underscore_d: That is actually the reverse question. That question is about constraints on the element type (must be `MoveAssignable` etc), this is about constraints on the container (if the element type is both copyable and movable, which one is chosen? Possible answers here include implementation-defined and unspecified). Since this question has a different set of possible answers, it cannot be a duplicate. – MSalters Oct 30 '17 at 15:56

2 Answers2

8

Are std::vector required to use move instead of copy, by standard?

I presume that you refer to move and copy of the elements.

Neither copy, nor move is necessarily required to be used at all, if you don't use the member functions that do those things. Some member functions are required to copy elements and other member functions are required to move elements.

When it required to use move constructor on reallocation

It is required to use move if the element is not copy insertable (this requires no rule, you can't do what you can't do). Otherwise it is required to copy if the move constructor can throw (this is required by strong exception guarantee quoted below). If non-throw of move can be proven, then it seems to be up to implementation, as I don't find any further guarantees. A good implementation would move when it is noexcept.

The exception guarantee on relevant functions:

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

eerorika
  • 232,697
  • 12
  • 197
  • 326
  • Ok, where it says that `vector` **required** to move on reallocation? And what exact conditions, for 100% move? – tower120 Oct 30 '17 at 14:38
  • @tower120 it depends on the type of object in the vector. Some move, some dont – 463035818_is_not_an_ai Oct 30 '17 at 14:44
  • 1
    @tower120 I amended my answer. I found no guarantees that I thought were there. – eerorika Oct 30 '17 at 14:46
  • "Otherwise it is required to copy if the move constructor can throw" What if both the copy and move constructors can throw? Then is it back to being up to the implementation? – Daniel H Oct 30 '17 at 15:04
  • 1
    @DanielH It's required to copy, because a copy constructor will not have side effects on the source objects so the possibility of a throw has no effect on the exception guarantee. – eerorika Oct 30 '17 at 15:10
  • So, to be clear, a vector implementation is *never* required to call the move constructor when reallocating; you can have a correct implementation which always reallocates with the copy constructor? – Daniel H Oct 30 '17 at 15:16
  • 1
    @DanielH You can leave only move constructor. It will be forced to move:) But otherwise, it seems like a gap in standard. – tower120 Oct 30 '17 at 15:18
2

Answer of user2079303 is good, but I summarize, just for myself.

Standard C++17 does not require std::vector to move during reallocation, at all. It allowed to always use copy, if object is copyable.

For example, std::vector<std::vector<std::array<char, 10000>>> is allowed to copy each time, when it need to reallocate its elements on grow.

Don't put your trust on library implementers, always check how YOUR copyable + movable type work with std::vector in YOUR environment. It could be anything, because it allowed to be anything.

tower120
  • 5,007
  • 6
  • 40
  • 88