2009-09-25 17 views
70

ejemplo Contrived, por el bien de la pregunta:¿Por qué no está el operador [] const para los mapas STL?

void MyClass::MyFunction(int x) const 
{ 
    std::cout << m_map[x] << std::endl 
} 

Esto no se compilará, ya que el operador [] es no constante.

Esto es desafortunado, ya que la sintaxis [] se ve muy limpia. En su lugar, tengo que hacer algo como esto:

void MyClass::MyFunction(int x) const 
{ 
    MyMap iter = m_map.find(x); 
    std::cout << iter->second << std::endl 
} 

Esto siempre me ha molestado. ¿Por qué el operador [] no es const?

+4

¿Qué debe 'operador []' rendimiento en el caso el elemento dado no existe? –

+1

@Frerich Raabe: Lo mismo que en la función miembro en: throw std :: out_of_range –

Respuesta

76

Para std::map, operator[] se inserte el valor de índice en el recipiente si no existía previamente. Es un poco intuitivo, pero así son las cosas.

Como se debe permitir que falle e inserte un valor predeterminado, el operador no se puede usar en una instancia const del contenedor.

http://en.cppreference.com/w/cpp/container/map/operator_at

+1

'std :: set' no tiene' operator [] '. – avakar

+0

Vaya, eso es correcto. Editado – Alan

+0

Esa es la respuesta correcta, pero una versión const podría hacer lo mismo que el miembro "at". Eso es tirar un std :: out_of_range ... –

0

Un operador de índice solo debe ser const para un contenedor de solo lectura (que realmente no existe en STL per se).

Los operadores de índice no solo se utilizan para ver valores.

+4

La pregunta es, ¿por qué no tiene dos versiones sobrecargadas? Una 'const', otra' 'non-'const' como, por ejemplo, 'std :: vector' hace. –

26

Nota para nuevos lectores.
La pregunta original era sobre contenedores STL (no específicamente sobre el std :: map)

Cabe señalar que hay una versión const del operador [] en la mayoría de los contenedores.
Es solo que std :: map y std :: set no tienen una versión const y esto es el resultado de la estructura subyacente que los implementa.

De std :: vector

reference  operator[](size_type n) 
const_reference operator[](size_type n) const 

También para su segundo ejemplo, usted debe comprobar si hay un fracaso en la búsqueda del elemento.

void MyClass::MyFunction(int x) const 
{ 
    MyMap iter = m_map.find(x); 
    if (iter != m_map.end()) 
    { 
     std::cout << iter->second << std::endl 
    } 
} 
+0

'std :: set' no tiene' operator [] 'en absoluto. – Everyone

0

Si usted declara su std :: mapa variable miembro para ser mutable

mutable std::map<...> m_map; 

puede utilizar las funciones miembro no const std :: mapa de dentro de sus métodos constantes.

+13

Esta es una idea terrible, sin embargo. – GManNickG

+0

¿Por qué es esta una idea terrible? –

+6

La API de tu clase miente si lo haces. La función afirma que es const, lo que significa que no modificará ninguna variable miembro, pero en realidad podría estar modificando el miembro de datos m_map. – Runcible

3

Dado que el operador [] podría insertar un nuevo elemento en el contenedor, no puede ser una función constante. Tenga en cuenta que la definición de operador [] es extremadamente simple: m [k] es equivalente a (* ((m.insert (value_type (k, data_type()))) first)). Second. En sentido estricto, esta función de miembro es innecesaria: no existe más que por conveniencia

41

Ahora que con C++ 11 que puede tener una versión más limpia mediante el uso de at()

void MyClass::MyFunction(int x) const 
{ 
    std::cout << m_map.at(x) << std::endl; 
} 
+3

Si 'map' tiene const y non-const' at() 's - ¿por qué no lo mismo también para' operator [] '? con la versión const no insertando nada sino más bien arrojando? (O devolviendo un opcional, cuando std :: opcional lo convierte en el estándar) – einpoklum

+0

@einpoklum El punto de precisión de la coincidencia es principalmente la verificación estática en tiempo de compilación. Prefiero que el compilador se queje que lanzar una excepción porque no usé objetos const correctamente. –

Cuestiones relacionadas