5
std::map<int, Obj> mp;
// insert elements into mp

// case 1
std::map<int, Obj> mp2;
mp2 = std::move(mp);

// case 2
std::map<int, Obj> mp3;
std::move(std::begin(mp), std::end(mp), std::inserter(mp3, std::end(mp3));

I am confused by the two cases. Are they exactly the same?

3
  • 1
    The first one has a constant time complexity, the second one has nlogn time complexity.
    – 3CxEZiVlQ
    Commented Nov 11, 2021 at 6:58
  • no they are not the same. Note that destination map in second case can be a bit different (for example have different order). Case 1 is super fast, case 2have to allocate some internal structure of map for mp3.
    – Marek R
    Commented Nov 11, 2021 at 6:59
  • Note that first copy just moves the entire tree from first map to second one, first one (usually) remaining empty, while second variant due to the nature of std::move leaves the nodes in second tree as are, just their contents being moved: Assume std::map<std::vector<...>>, then the vector's contents are moved, while the vectors in the first map themselves remain (usually empty).
    – Aconcagua
    Commented Nov 11, 2021 at 7:29

2 Answers 2

5

No, they are not the same.

  • Case 1 moves the content of the whole map at once. The map's internal pointer(s) are "moved" to mp2 - none of the pairs in the map are affected.
  • Case 2 moves the individual pair's in the map, one by one. Note that map Key s are const so they can't be moved but will instead be copied. mp will still contain as many elements as before - but with values in an indeterminable state.
5

Are they exactly the same?

No, They are not!

The first one invokes the move constructor of the std::map4 and the move operation will be done at class/ data structure level.

[...]

  1. Move constructor. After container move construction (overload (4)), references, pointers, and iterators (other than the end iterator) to other remain valid, but refer to elements that are now in *this. The current standard makes this guarantee via the blanket statement in container.requirements.general, and a more direct guarantee is under consideration via LWG 2321

Complexity

4) Constant. If alloc is given and alloc != other.get_allocator(), then linear.


The second std::move is from <algorithm> header, which does element wise(i.e. key value pairs) movement to the other map.

  1. Moves the elements in the range [first, last), to another range beginning at d_first, starting from first and proceeding to last - 1. After this operation the elements in the moved-from range will still contain valid values of the appropriate type, but not necessarily the same values as before the move.

Complexity

Exactly last - first move assignments.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.