Can I always use emplace to replace an insert to insert a single item?

I was wondering if it is okay to use emplace to replace insert when inserting one element into an STL container, like set, unordered_set?

From a signature, emplace simpler and not overloaded. Is there a problem with stopping using insert and using emplace all the time?

Note: there are SO questions regarding the difference between emplace and insert / push_back , etc. (e.g. here , here , and here ). I understand the difference, and it seems to me that emplace better in every way. I just want to confirm if it is OK to denounce insert .

+6
source share
2 answers

There are a few examples here that can be adapted to emplace and insert , showing when the behavior may differ.

These examples may seem a little artificial, so I will give one that I hope will look smaller:

 #include <set> template <typename T> T id(T x) { return x; } int main() { std::set<int(*)(int)> s; s.insert(id); // OK s.emplace(id); // error s.emplace(id<int>); // OK } 

insert can infer id template parameter because it knows what type it wants. For emplace you will get an error if you have not explicitly specified.

+4
source

Always? No, of course not.

Consider the following example, which uses std::vector for simplicity (suppose that uptr is a smart pointer that acts as a whole like std::unique_ptr ):

 std::vector<uptr<T>> vec; vec.insert(vec.begin(), new T()); 

This is safe for exceptions. A temporary uptr is created to go to insert , which moves to the vector. If the redistribution of the vector fails, the highlighted T belongs to the smart pointer, which correctly deletes it.

Compare with:

 std::vector<std::uptr<T>> vec; vec.emplace(vec.begin(), new T()); 

emplace not allowed to create a temporary object. uptr will be created once, in place in the vector. If the redistribution is not performed, there is no place to create in place, and no smart pointer will be initialized. T will leak out.

Of course, the best alternative is:

 std::vector<std::unique_ptr<T>> vec; vec.insert(vec.begin(), make_unique<T>()); 

which uses a standard smart pointer and makes creating a smart pointer explicit.

+4
source

Source: https://habr.com/ru/post/972518/


All Articles