C++ map access descarta calificadores (const)


El siguiente código dice que pasar el mapa como const al método operator[] descarta calificadores:

#include <iostream>
#include <map>
#include <string>

using namespace std;

class MapWrapper {
public:
    const int &get_value(const int &key) const {
        return _map[key];
    }

private:
    map<int, int> _map;
};

int main() {
    MapWrapper mw;
    cout << mw.get_value(42) << endl;
    return 0;
}

¿Esto se debe a la posible asignación que se produce en el acceso al mapa? ¿No se puede declarar const ninguna función con acceso a mapas?

MapWrapper.cpp:10: error: passing ‘const std::map<int, int, std::less<int>, std::allocator<std::pair<const int, int> > >’ as ‘this’ argument of ‘_Tp& std::map<_Key, _Tp, _Compare, _Alloc>::operator[](const _Key&) [with _Key = int, _Tp = int, _Compare = std::less<int>, _Alloc = std::allocator<std::pair<const int, int> >]’ discards qualifiers

Author: cdleary, 2008-11-04

5 answers

std::map's operator [] no se declara como const, y no puede ser debido a su comportamiento:

T& operator [] (const Key& key)

Devuelve una referencia al valor que se asigna a una clave equivalente a clave, realizando la inserción si dicha clave no existe ya.

Como resultado, su función no puede ser declarada const, y usar el mapa operator[].

std::map's find() función le permite buscar una tecla sin modificar el asignar.

find() devuelve un iterator, o const_iterator para un std::pair contiene tanto la llave (.first) y el valor (.second).

En C++11, también podría usar at() para std::map. Si el elemento no existe, la función lanza una excepción std::out_of_range, en contraste con operator [].

 126
Author: luke,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-01-10 19:46:17

No puede usar operator[] en un mapa que es const ya que ese método no es const ya que le permite modificar el mapa (puede asignarlo a _map[key]). Intente usar el método find en su lugar.

 10
Author: nlativy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-03-13 23:07:01

Desde operator[] no tiene una sobrecarga calificada const, no se puede utilizar con seguridad en una función calificada const. Esto se debe probablemente a que la sobrecarga actual se construyó con el objetivo de devolver y establecer valores clave.

En su lugar, puede usar:

VALUE = map.find(KEY)->second;

O, en C++11, puede utilizar el at() operador:

VALUE = map.at(KEY);
 9
Author: Richard,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-01-23 22:28:02

Algunas versiones más recientes de los encabezados GCC (4.1 y 4.2 en mi máquina) tienen funciones miembro no estándar map::at() que se declaran const y arrojan std::out_of_range si la clave no está en el mapa.

const mapped_type& at(const key_type& __k) const

De una referencia en el comentario de la función, parece que esto ha sido sugerido como una nueva función miembro en la biblioteca estándar.

 7
Author: Nathan Kitchen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-11-04 19:00:44

Primero, no debe usar símbolos que comiencen con _ porque están reservados al escritor de implementación/compilador del lenguaje. Sería muy fácil para _map ser un error de sintaxis en el compilador de alguien, y no tendría a nadie a quien culpar sino a usted mismo.

Si desea usar un guion bajo, póngalo al final, no al principio. Probablemente cometiste este error porque viste algún código de Microsoft haciéndolo. Recuerde, escriben su propio compilador, por lo que pueden ser capaces de escapar consigo. Aun así, es una mala idea.

El operador [] no solo devuelve una referencia, sino que crea la entrada en el mapa. Así que no solo está obteniendo un mapeo, si no hay ninguno, está creando uno. Eso no es lo que pretendías.

 0
Author: Dov,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-03-22 11:18:12