-1

I want to understand how to use emplace() method in unordered_map I have two functions foo1 and foo2, did I understand correctly that I don't have extra copy only in foo2? How can I check it?

My code

struct A {
   void foo1(const std::string& s) {
      cnt.emplace(s, 1);
   }

   void foo2(std::string&& s) {
      cnt.emplace(s, 1);
   }

   std::unordered_map<std::string, int> cnt;
};


int main() {
    A a;
    a.foo1("AAAA");
    a.foo2("AAAA");
}

mascai
  • 1,373
  • 1
  • 9
  • 30
  • 3
    You need to use `cnt.emplace(std::move(s), 1)` in `foo2`. – Weijun Zhou Aug 24 '23 at 17:13
  • You have to use `std::move(s)` to move the string. But you are correct that this will only work for `foo2`. A const string cannot be moved. – BoP Aug 24 '23 at 17:14
  • 4
    The literal constant string `"AAAA"` is not a `std::string` object, it's an array of five constant characters somewhere in memory. For both `foo1` and `foo2` a `std::string` object needs to be created, and it will be copied into your map for *both* `foo1` and `foo2` (***if*** you only call one of the functions, because otherwise the element already exist and won't be recreated). – Some programmer dude Aug 24 '23 at 17:14
  • And you might want to prefer `try_emplace`. – Evg Aug 24 '23 at 17:14
  • @WeijunZhou and @BoP are correct: you have to mark `s` as being an rvalue with `std::move()`. But pls note that the actual move doesn't take place here. If you refer to https://en.cppreference.com/w/cpp/container/unordered_map/emplace , the point of `emplace` is that the new element within the map (the "node" one might say) is constructed in situ and not constructed outside, then copied (or rather moved) into the map. That is your `s` is used during construction of the new element. When, additionally, `s` comes in as rvalue, then it might even be moved into the new element during construction. – kaba Aug 24 '23 at 19:43
  • But @Someprogrammerdude is correct as well, of course. In your example you use `char const*` as bases under the hood. The `std::string` temporary objects are created upon calling `foo1` and `foo2`. So anything that comes after that may be ironed out by a clever optimiser anyway? You can always use a custom class instead of `std::string` and instrument all the constructors and the destructor with `std::cout`s to see what's happening (but be sure to try different optimiser settings). – kaba Aug 24 '23 at 19:48

0 Answers0