Middle
Cosa bisogna fare per memorizzare la propria struttura in un unordered_map?
sobes.tech AI
Risposta dell'AI
Per memorizzare una struttura come chiave in std::unordered_map, è necessario fornire:
- Funzione di hash (hash function): Trova il valore hash per un'istanza della struttura.
- Operatore di confronto di uguaglianza (
operator==): Confronta due istanze della struttura per verificare se sono uguali.
Ci sono diversi modi per fornire questi elementi:
-
Sovraccaricare
operator==all'interno della struttura e specializzarestd::hashper la tua struttura. Questo è l'approccio più comune e raccomandato.#include <unordered_map> #include <string> #include <functional> struct MyStruct { int id; std::string name; bool operator==(const MyStruct& other) const { return id == other.id && name == other.name; } }; // Specializzazione di std::hash per MyStruct namespace std { template <> struct hash<MyStruct> { size_t operator()(const MyStruct& obj) const { size_t h1 = hash<int>()(obj.id); size_t h2 = hash<std::string>()(obj.name); return h1 ^ (h2 << 1); } }; } // Esempio di utilizzo in main int main() { std::unordered_map<MyStruct, int> my_map; MyStruct key1 = {1, "Alice"}; MyStruct key2 = {2, "Bob"}; MyStruct key3 = {1, "Alice"}; // equivalente a key1 my_map[key1] = 10; my_map[key2] = 20; if (my_map.count(key3)) { // my_map[key3] restituirà 10 } return 0; } -
Fornire funzioni di hash e confronto come parametri separati nella dichiarazione di
unordered_map. Meno comodo se si utilizza frequentemente la struttura come chiave, poiché è necessario specificare i tipi di comparatore e hash ad ogni dichiarazione del contenitore.#include <unordered_map> #include <string> #include <functional> struct MyStruct { int id; std::string name; }; // Funzione di hash separata struct MyStructHash { size_t operator()(const MyStruct& obj) const { size_t h1 = std::hash<int>()(obj.id); size_t h2 = std::hash<std::string>()(obj.name); return h1 ^ (h2 << 1); } }; // Funzione di confronto separata struct MyStructEqual { bool operator()(const MyStruct& lhs, const MyStruct& rhs) const { return lhs.id == rhs.id && lhs.name == rhs.name; } }; // Esempio di utilizzo in main int main() { std::unordered_map<MyStruct, int, MyStructHash, MyStructEqual> my_map; MyStruct key1 = {1, "Alice"}; MyStruct key2 = {2, "Bob"}; my_map[key1] = 10; my_map[key2] = 20; return 0; }
Punti importanti:
- Correttezza della funzione di hash: Per ogni coppia di chiavi
aeb, sea == b, allorahash(a)deve essere uguale ahash(b). Il contrario non è richiesto (possono esserci collisioni). - Qualità della funzione di hash: Una buona funzione di hash distribuisce uniformemente i valori di hash per diverse chiavi, minimizzando le collisioni e migliorando le prestazioni (
O(1)in media). - Constanza: Gli operatori di confronto e la funzione di hash devono essere
const, poiché non devono modificare l'oggetto chiave.