Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

At which point does map::emplace create an object?

Is the point at which std::map::emplace creates the object (i.e. call the constructor) specified somehow in standard? If yes, does it happen before existence of such key is checked or after?

It matters a lot in the cases like following:

struct X {};
std::map<int, std::unique_ptr<X> > map;

void f(int x) {
    map.emplace(x, new X);
}

If object is created first, all is cool (unique_ptr is constructed and owns the resource), but if it is constructed after the check, there is a memory leak in case of a duplicate key.

All I was able to find in Standard is

Inserts a value_type object t constructed with std::forward<Args>(args)... if and only if there is no element in the container with key equivalent to the key of t.

which doesn't address the question I have.

like image 787
SergeyA Avatar asked May 05 '16 21:05

SergeyA


People also ask

What is map emplace?

map emplace() in C++ STL The map::emplace() is a built-in function in C++ STL which inserts the key and its element in the map container.

When to use try_ emplace?

In most cases, you should use try_emplace . In particular, if two conditions hold: You are inserting a single object at a time. You are creating a new mapped-to value and/or (key, value) pair just to insert it into the map.

What is emplace in C++?

The vector::emplace() is an STL in C++ which extends the container by inserting a new element at the position. Reallocation happens only if there is a need for more space.

What is emplace in queue?

queue::emplace() is used to insert or emplace a new element in the queue container. As the functionality of the queue structure is that the element inserted to the end of the structure, to emplace() calls the emplace_back() for the successful insertion of the element at the end of the queue container.


1 Answers

This is indeed underspecified, which is partially why C++17 added try_emplace to nail down the semantics. N3873, an early version of the try_emplace proposal, has a good discussion on the existing wording.

In the general case, it has to be "before", as "after" is unimplementable, and the standard would be defective if it imposed such a requirement. Consider emplace(piecewise_construct, forward_as_tuple(foo, bar), forward_as_tuple(meow, purr)). As the key and value are not required to be movable, you pretty much have to construct the object first and check the key's existence second, because you can't check for the key's existence without the key.

It is not inconceivable, however, that an implementation might want to special-case emplace(key_type, something); it's usually a Good Thing to avoid paying for the required allocation + construction + destruction + deallocation when the key exists.

like image 80
T.C. Avatar answered Oct 20 '22 09:10

T.C.