Acceso a elementos de mapa const de C ++

100

Intenté usar el operador [] para acceder al elemento en un mapa constante de C ++, pero este método falló. También intenté usar "at ()" para hacer lo mismo. Funcionó esta vez. Sin embargo, no pude encontrar ninguna referencia sobre el uso de "at ()" para acceder al elemento en un mapa constante de C ++. ¿Es "at ()" una función recién agregada en el mapa C ++? ¿Dónde puedo encontrar más información sobre esto? ¡Muchas gracias!

Un ejemplo podría ser el siguiente:

#include <iostream>
#include <map>

using namespace std;

int main()
{
        map<int, char> A;
        A[1] = 'b';
        A[3] = 'c';

        const map<int, char> B = A;

        cout << B.at(3) << endl; // it works
        cout << B[3] << endl;  // it does not work

}

Para usar "B [3]", devolvió los siguientes errores durante la compilación:

t01.cpp: 14: error: pasar 'const std :: map, std :: allocator>>' como 'este' argumento de '_Tp & std :: map <_Key, _Tp, _Compare, _Alloc> :: operator [] ( const _Key &) [con _Key = int, _Tp = char, _Compare = std :: less, _Alloc = std :: allocator>] 'descarta los calificadores

El compilador utilizado es g ++ 4.2.1

icephere
fuente

Respuestas:

124

at()es un nuevo método para std::mapen C ++ 11.

En lugar de insertar un nuevo elemento construido por defecto como operator[]ocurre si un elemento con la clave dada no existe, lanza una std::out_of_rangeexcepción. (Esto es similar al comportamiento de at()for dequey vector.)

Debido a este comportamiento, tiene sentido que haya una constsobrecarga de at(), a diferencia de lo operator[]que siempre tiene el potencial de cambiar el mapa.

CB Bailey
fuente
¿Es posible que "at" devuelva un valor predeterminado en lugar de lanzar una excepción?
user1202136
Estoy usando at()en VS2013 en un proyecto configurado para usar el kit de herramientas VS2010. Pensé que eso significaba que no estaba usando C ++ 11 ... ¿Pero aún se compila ... ??
thomthom
1
Solo necesito comentar que no tiene sentido omitir el operador const [], que también podría generar una excepción para un elemento no mapeado en lugar de cambiar el mapa.
Spencer
@Spencer Sería sorprendente si las sobrecargas const y no const de operator [] tuvieran efectos diferentes. Normalmente, esperamos que si algunos objetos o referencias que no son constantes en un programa se hacen constantes, el programa continuará comportándose de la misma manera, siempre que se compile. Permitir que solo la sobrecarga no constante genere excepciones puede generar errores que no se detectan hasta el tiempo de ejecución.
Brian
@Brian ¿Quisiste decir "Permitir que solo la sobrecarga constante genere excepciones"?
Spencer
33

Si un elemento no existe en a map, operator []lo agregará, lo que obviamente no puede funcionar en un constmapa, por lo que C ++ no define una constversión del operador. Este es un buen ejemplo del verificador de tipos del compilador que evita un posible error en tiempo de ejecución.

En su caso, debe usar finden su lugar, que solo devolverá un (iterador al) elemento si existe, nunca modificará el map. Si un elemento no existe, devuelve un iterador al mapa end().

atno existe y ni siquiera debería compilarse. Quizás esta sea una "extensión del compilador" (=un insecto nuevo en C ++ 0x).

Konrad Rudolph
fuente
¿El estándar C ++ prohíbe que la implementación defina funciones miembro adicionales no estándar en clases de biblioteca?
Tim Martin
@Tim Creo que la interfaz está arreglada, sí.
Konrad Rudolph
4

El operador [] creará una nueva entrada en el mapa si la clave dada no existe. Por tanto, puede cambiar el mapa.

Vea este enlace .

vidstige
fuente