5
class TestClass {
    public:
     TestClass(string s) {

     }
   };

When there is TestClass, I understand the difference between emplace and insert (emplace constructs in place while insert copies)

   set<TestClass> test_set;
   test_set.insert(TestClass("d"));
   test_set.emplace("d");

However, if there is already a TestClass object, how are they different in terms of mechanism and preformance?

   set<TestClass> test_set;
   TestClass tc("e");
   test_set.insert(tc);
   test_set.emplace(tc);
MaxHeap
  • 1,138
  • 2
  • 11
  • 20

2 Answers2

8

emplace does its work by perfect forwarding its parameters to the right constructor (by using likely a placement new in most of the implementations).
Because of that, in your case it forwards an lvalue reference and thus it invokes likely the copy constructor.
What's now the difference with a push_back that explicitly calls the copy constructor?

Meyers also cites that in one of his books, and he says that there is no actual gain in calling emplace if you already have an instance of the object.

skypjack
  • 49,335
  • 19
  • 95
  • 187
  • 1
    Actually, not that there is only _no actual gain_, but there may also be _performance loss_. `emplace` needs to construct the key first, and since the key may be both non-copyable and non-movable, it needs to construct the key in the allocated node. On the contrary, `insert` does not need to allocate when the key is already present in the map. – Daniel Langr Apr 13 '22 at 09:51
2

Careful use of emplace allows the new element to be constructed while avoiding unnecessary copy or move operations. The constructor of the new element is called with exactly the same arguments as supplied to emplace, forwarded via std::forward(args)....

Reference here leads me to believe that such non-"careful use" would lead to very similar mechanism and performance as insert, the exact details of which may be compiler specific.

fetherolfjd
  • 276
  • 1
  • 11