Riferimenti all'oggetto C ++ vs. ricerca

2

Supponiamo che ci siano 2 classi: Paese e Città. Entrambi hanno nomi, quindi una mappa si adatterebbe come conainer

map<std::string, Country> countries;

Nella classe Paese c'è una mappa simile che contiene tutte le città - per semplicità, diciamo che è pubblica:

map<std::string, City> cities;

Ora al primo livello se una città specifica deve essere indirizzata, la richiesta assomiglia a questa:

countries.at("Japan").cities.at("Tokyo");

(Nel mondo reale dovrei piuttosto usare find e controllare ogni volta se il paese / città desiderato esiste realmente, giusto?)

Ora diciamo al livello più alto che vogliamo memorizzare in un vettore un insieme delle nostre città preferite. Vedo 2 opzioni per farlo:

// Option 1: Store the cities as references: 
vector<City&> favouriteCities;

// Option 2: Store the ID's (Names) of the countries and the cities as strings
vector<pair<std::string,std::string>> favouriteCities;

Quindi per ottenere la mia prima città preferita nell'opzione 2 dovrò accedervi in questo modo:

countries.at(favouriteCities[0].first).cities.at(favouriteCities[0].second);

Quali sarebbero i pro e i contro di queste opzioni? AFAIK: l'opzione 1 è più performante e più conveniente. Ma con l'opzione 2 hai la possibilità di controllare se la città preferita desiderata è ancora nel sistema e non è stata eliminata nel frattempo (quindi un riferimento non sarebbe valido).

Ci sono altri punti da considerare?

    
posta Stefan Woehrer 08.03.2016 - 13:23
fonte

2 risposte

3

L'opzione 2 è sicuramente la migliore.

Il principale vantaggio dell'opzione 1 è che è impossibile; i contenitori standard non possono contenere riferimenti.

Sebbene tu possa "fingere" usando std::ref , non è mai una buona idea archiviare le maniglie negli elementi del contenitore. Cosa succede quando quegli elementi sono invalidati dalla cancellazione della mappa? A peggiore vuoi un std::unique_ptr , e nella migliore delle ipotesi vuoi usare i comodi tasti stringa che già usi.

Se scopri (attraverso la profilazione!) che i confronti tra stringhe sono un collo di bottiglia, solo allora prendi in considerazione l'implementazione di qualcosa di più complesso, una soluzione più "algoritmica".

    
risposta data 08.03.2016 - 14:15
fonte
1

Invece di un semplice riferimento, è possibile memorizzare un shared_ptr della città o del paese, quindi può essere rimosso dalla mappa ed esiste ancora in memoria (ad esempio se è ancora preferito). Verrà cancellato dalla memoria solo quando tutti i riferimenti verranno rimossi.

In alternativa, puoi memorizzare le voci City e Country in un contenitore (ad es. un vettore così da guadagnare da un blocco contiguo di memoria) appositamente per tenerle, e avere entrambi i preferiti e la mappa puntare a queste voci iniziali - un po 'come un approccio "malloc and pointer" di altissimo livello. Il concetto è che hai 1 entità che detiene la proprietà degli oggetti, e tutto il resto può quindi semplicemente riferirsi o puntare a loro senza preoccupazioni sulla proprietà e sulla vita degli oggetti.

    
risposta data 08.03.2016 - 13:54
fonte

Leggi altre domande sui tag