Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Copy/move requirements for the key/value types in a std::map?

Tags:

c++

c++11

This code confuses me:

struct foo {
  int i;

  foo(int j) : i(j) {}

  foo(const foo &) = delete;
  foo(foo &&) = delete;
  foo &operator=(const foo&) = delete;
  foo &operator=(foo&&) = delete;
};

bool operator<(const foo &f1, const foo &f2)
{
  return f1.i < f2.i;
}

int main(int argc, char **argv)
{
  std::map<foo,int> f;
  std::map<foo,int> f2 = f; //error (as expected)
  std::map<foo,int> f3 = std::move(f); //no error (why?)
  return 0;
}

Because I get no error there, it seems like when moving a map no key object is created (not even for moving another key object into it).

Why not? Can I rely on this behavior according to the C++11 standard?

More generally, what copying/moving requirements does a std::map place on the key and value types and under what conditions?

like image 369
roger.james Avatar asked Jul 11 '13 21:07

roger.james


People also ask

Can C++ copy maps?

Starting with C++17, we can use the std::map::merge member function to copy content from a map to another map. This is the recommended way to copy the contents of a map to an existing map in C++17 and above. That's all about copying entries of a map to another map in C++.

How do I change the value of STD in map?

To update an existing value in the map, first we will find the value with the given key using map::find() function. If the key exists, then will update it with new value.

Does map insert copy?

Yes -- when you insert an item into an std::map, you pass it by value, so what it contains is a copy of what you passed.


1 Answers

Copy-assignment of one map to another requires copying each item. Since you cannot copy items, you cannot copy-assign the maps.

Whether the actual map object is empty at runtime is immaterial, since these are purely static considerations, determined entirely by the types of the objects.

(It's like asking why sin(0) requires a floating point unit when clearly the result is an integer.)

Moving the entire map, on the other hand, is fine because the container is node-based and no actual values are mutated, just the nodes are. In fact, move-constructing or move-assigning node based containers doesn't require the elements to be copyable or movable or assignable at all.

(This should be true for all containers that manage dynamic memory in a suitable fashion, such as via std::allocator<value_type>, but it would of course not be true for something like std::array, and it would be interesting whether or not it would hold for std::dynarray, and as @Jonathan Wakely noted, if the allocation scheme isn't able to move nodes wholesale.)

like image 196
Kerrek SB Avatar answered Oct 14 '22 19:10

Kerrek SB