Pytanie Mapa STL - wstaw lub zaktualizuj


Mam mapę obiektów i chcę zaktualizować obiekt zmapowany do klucza lub utworzyć nowy obiekt i wstawić go na mapę. Aktualizacja odbywa się za pomocą innej funkcji, która pobiera wskaźnik do obiektu (void update (MyClass * obj))

Jaki jest najlepszy sposób "wstawienia lub aktualizacji" elementu na mapie?


15
2018-05-07 06:32


pochodzenie




Odpowiedzi:


The operator[] 


17
2018-05-07 06:35



Może to dać elegancki kod, jeśli chcesz wstawić wartość domyślną MyClass obiekt, a następnie zaktualizuj go. Jeśli chcesz wstawić inny niż domyślny obiekt lub nie zaktualizować wstawionej wartości, rozwiązanie Charlesa jest prawdopodobnie lepsze. - Dennis Zickefoose
update(my_map[key])? To też by oznaczało, że ty update zawsze (co nie wynika z pytania). - UncleBens
Co jeśli klucz nie istnieje? - Konrad
@Konrad: Domyślny skonstruowany element zostanie wstawiony i zwrócony. To może być pożądana semantyka, ale zależy od tego, jak wszystko działa. - Dennis Zickefoose


W przypadku podobnego do poniższego fragmentu:

std::map<Key, Value>::iterator i = amap.find(key);

if (i == amap.end())
    amap.insert(std::make_pair(key, CreateFunction()));
else
    UpdateFunction(&(i->second));

Jeśli chcesz zmierzyć coś, co może poprawić wydajność, z której możesz skorzystać .lower_bound() aby znaleźć miejsce, w którym wpis i użycie stanowią podpowiedź do wstawienia w przypadku, gdy trzeba wstawić nowy obiekt.

std::map<Key, Value>::iterator i = amap.lower_bound(key);

if (i == amap.end() || i->first != key)
    amap.insert(i, std::make_pair(key, CreateFunction()));
                                       // Might need to check and decrement i.
                                       // Only guaranteed to be amortized constant
                                       // time if insertion is immediately after
                                       // the hint position.
else
    UpdateFunction(&(i->second));

9
2018-05-07 06:42



Myślę, że skutecznie musisz zmniejszyć i jeśli nie jest równy amap.begin(). I w związku z tym oczywiste pytanie: jak dać wskazówkę, że należy go umieścić na pierwszym miejscu? Przypuszczam, że działa z wersją bez podpowiedzi: / - Matthieu M.
Tak, to trochę warty wymóg. Implementacja mógłby sprawiają, że jest to skuteczne, jeśli wskazówka była natychmiast po pozycji wstawienia. Wydaje się, że jest to lepsze ... i tak zostało naprawione: open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#233 - CB Bailey


coś jak:

map<int,MyClass*> mymap;
map<int,MyClass*>::iterator it;

MyClass* dummy = new MyClass();
mymap.insert(pair<int,MyClass*>(2,dummy));

it = mymap.find(2);
update(it.second);

tutaj miłe odniesienie połączyć


1
2018-05-07 06:39



Jeśli zamierzasz iść tą drogą: MyClass& obj = mymap[2]; update(&obj); - Dennis Zickefoose
Tak, ale z [] powinieneś wiedzieć, że jeśli obiekt nie istnieje, tworzy nowy (co powoduje, że sekunda jest wskaźnikiem zerowym) - RvdK
Nie. Jeśli klucz nie jest obecny, wstawia jeden, a następnie zwraca odniesienie do niego. Masz gwarancję, że otrzymasz prawidłowy obiekt, o ile będzie na to pamięć. Nawet gdyby to nie było zachowanie, z pewnością nie dałoby to nieważnego odniesienia. W tym przypadku wyjątek jest znacznie bardziej prawdopodobny. - Dennis Zickefoose
Och, wyciek pamięci. - Matthieu M.
@Dennis Tak, utworzy nową parę, ale wartość (it.second) jest wskaźnikiem do obiektu MyClass, który nie został ustawiony. - RvdK


The operator[] już robi, co chcesz. Widzieć referencje dla szczegółów.


1
2018-05-07 14:27



co dziwne, odnośnik jest błędny. Odwołanie mówi, że operator [] jest równoważny wstawianiu, ale zastępczo (std :: make_pair ("a", "1")); przykładsert (std :: make_pair ("a", "2")); nie aktualizuje m. m ["a"] pozostaje "1". m ["a"] = "2" zaktualizuje m. Gdzie: map <string, string> m; - DavidPhillipOster