2010-05-07 13 views
12

Tengo un mapa de objetos y deseo actualizar el objeto asignado a una clave, o crear un nuevo objeto e insertarlo en el mapa. La actualización se realiza mediante una función diferente que toma un puntero al objeto (actualización vacía (MyClass * obj))Mapa de STL - insertar o actualizar

¿Cuál es la mejor manera de "insertar o actualizar" un elemento en un mapa?

Respuesta

16

El operator[]      

+3

Esto puede generar código elegante, si desea insertar un objeto 'MyClass' predeterminado, y luego actualizarlo. Si necesita insertar un objeto no predeterminado, o no actualiza el valor insertado, la solución de Charles es probablemente mejor. –

+1

'update (my_map [key])'? Eso también significa que 'update' always (que no está claro en la pregunta). – UncleBens

+0

¿Qué pasa si la clave no existe? – Konrad

0

algo como:

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); 

aquí una buena referencia link

+0

Si vas a seguir esa ruta: 'MyClass & obj = mymap [2]; update (&obj); ' –

+0

Sí, pero con [] debe saber que si el objeto no existe, crea uno nuevo (lo que resulta que el segundo es un puntero nulo) – RvdK

+0

No. Si la clave no está presente, inserta una, y luego devuelve una referencia al mismo. Por lo tanto, tiene la garantía de obtener un objeto válido siempre que haya memoria para él. Incluso si ese no fuera el comportamiento, ciertamente no arrojaría una referencia inválida. Una excepción es mucho más. Probablemente en ese caso. –

7

Con algo como el siguiente fragmento:

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

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

Si desea medir algo que pueda mejorar el rendimiento, es posible que desee utilizar .lower_bound() para encontrar una entrada y usarla como una sugerencia para insertar en el caso donde necesite insertar un nuevo objeto.

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)); 
+0

Creo que efectivamente necesitas disminuir 'i' si no es igual a' amap.begin() ' . Y así el obviou s pregunta: ¿cómo dar como una pista que debe insertarse en la primera posición? Supongo que funciona con la versión sin pistas:/ –

+0

Sí, es un requisito un tanto vergonzoso. Una implementación * podría * hacerlo eficiente si la sugerencia fue inmediatamente después de la posición de inserción. Esto parece ser más nítido ... y así es como se ha resuelto: http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#233 –

0

El operator[] ya lo hace, lo que quiere. Ver the reference para más detalles.

+0

por extraño que parezca, la referencia Está Mal. La referencia dice que operator [] es equivalente a insert, pero m.insert (std :: make_pair ("a", "1")); m.insert (std :: make_pair ("a", "2")); no actualiza m. m ["a"] permanece "1". m ["a"] = "2" actualizaría m. Donde: mapa m; – DavidPhillipOster

Cuestiones relacionadas