unordered_set unordered_map unordered example c++ c++11 unordered-map

unordered_set - unordered_map c++ example



¿Cuál es la diferencia entre unordered_map:: emplace y unordered_map:: insert en C++? (1)

unordered_map::insert copia o mueve un par clave-valor al contenedor. Está sobrecargado para aceptar referencia a const o una referencia rvalue :

std::pair<iterator,bool> insert(const std::pair<const Key, T>& value); template<class P> std::pair<iterator,bool> insert(P&& value);

unordered_map::emplace permite evitar copias o movimientos innecesarios al construir el elemento en su lugar. Utiliza un reenvío perfecto y una plantilla variadic para reference :

template<class... Args> std::pair<iterator,bool> emplace(Args&&... args);

Pero hay una gran cantidad de superposición entre las dos funciones. emplace se puede usar para reenviar al constructor de copia / movimiento del par clave-valor que permite que se use como lo haría insert . Esto significa que el uso de emplace no garantiza que evitará copias o movimientos. Además, la versión del insert que toma una referencia-r es en realidad una plantilla y acepta cualquier tipo P modo que el par clave-valor es construible a partir de P

Scott Meyers dice:

En principio, las funciones de emplazamiento a veces deberían ser más eficientes que sus contrapartes de inserción, y nunca deberían ser menos eficientes.

( Edit: Howard Hinnant realizó algunos experimentos que mostraron que algunas veces insert es más rápido que emplace )

Si definitivamente desea copiar / mover en el contenedor, puede ser conveniente utilizar insert porque es más probable que obtenga un error de compilación si pasa argumentos incorrectos. Debe tener más cuidado al pasar los argumentos correctos a las funciones de emplazamiento.

La mayoría de las implementaciones de unordered_map::emplace harán que la memoria se asigne dinámicamente para el nuevo par, incluso si el mapa ya contiene un elemento con esa clave y el emplace fallará. Esto significa que si existe una buena probabilidad de que falle un emplace , es posible que obtenga un mejor rendimiento al usar la función de inserción para evitar asignaciones de memoria dinámica innecesarias.

Pequeño ejemplo:

#include <unordered_map> #include <iostream> int main() { auto employee1 = std::pair<int, std::string>{1, "John Smith"}; auto employees = std::unordered_map<int, std::string>{}; employees.insert(employee1); // copy insertion employees.insert(std::make_pair(2, "Mary Jones")); // move insertion employees.emplace(3, "James Brown"); // construct in-place for (const auto& employee : employees) std::cout << employee.first << ": " << employee.second << "/n"; }

Edit2: a petición. También es posible usar unordered_map::emplace con una clave o valor que toma más de un parámetro de constructor. Usando el constructor std::pair partes , aún puede evitar copias o movimientos innecesarios.

#include <unordered_map> #include <iostream> struct Employee { std::string firstname; std::string lastname; Employee(const std::string& firstname, const std::string& lastname) : firstname(firstname), lastname(lastname){} }; int main() { auto employees = std::unordered_map<int, Employee>{}; auto employee1 = std::pair<int, Employee>{1, Employee{"John", "Smith"}}; employees.insert(employee1); // copy insertion employees.insert(std::make_pair(2, Employee{"Mary", "Jones"})); // move insertion employees.emplace(3, Employee("Sam", "Thomas")); // emplace with pre-constructed Employee employees.emplace(std::piecewise_construct, std::forward_as_tuple(4), std::forward_as_tuple("James", "Brown")); // construct in-place }

¿Cuál es la diferencia entre std::unordered_map::emplace y std::unordered_map::insert en C ++?