Ejemplo elaborado, por el bien de la pregunta:
void MyClass::MyFunction( int x ) const
{
std::cout << m_map[x] << std::endl
}
Esto no se compilará, ya que el operador [] no es constante.
Esto es lamentable, ya que la sintaxis [] parece muy limpia. En cambio, 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 constante?
operator[]
rendir en caso de que el elemento dado no exista?Respuestas:
Para
std::map
ystd::unordered_map
,operator[]
insertará el valor del índice en el contenedor si no existía previamente. Es un poco intuitivo, pero es así.Dado que se debe permitir que falle e inserte un valor predeterminado, el operador no se puede usar en una
const
instancia del contenedor.http://en.cppreference.com/w/cpp/container/map/operator_at
fuente
std::set
no tieneoperator[]
.std::vector
tiene un operador de lectura[]
que esconst
.map
debería hacer lo mismo.Ahora que con C ++ 11 puede tener una versión más limpia usando at ()
void MyClass::MyFunction( int x ) const { std::cout << m_map.at(x) << std::endl; }
fuente
map
tiene const y no constat()
s, ¿por qué no lo mismo también paraoperator[]
? con la versión const no insertando nada sino tirando? (O devolver un opcional, cuando std :: opcional lo convierte en el estándar)at
viene en dos sabores es porque hace areturn *this;
, y la única diferencia entre las sobrecargas es el carácterconst
de la referencia devuelta. Los efectos reales de ambosat
s son exactamente los mismos (es decir, sin efecto).Nota para nuevos lectores.
La pregunta original era sobre contenedores STL (no específicamente sobre std :: map)
Cabe señalar que existe una versión constante de operator [] en la mayoría de los contenedores.
Es solo que std :: map y std :: set no tienen una versión constante y esto es el resultado de la estructura subyacente que los implementa.
Desde std :: vector
reference operator[](size_type n) const_reference operator[](size_type n) const
Además, para su segundo ejemplo, debe verificar si no se encuentra el elemento.
void MyClass::MyFunction( int x ) const { MyMap iter = m_map.find(x); if (iter != m_map.end()) { std::cout << iter->second << std::endl } }
fuente
std::set
no tieneoperator[]
nada.Dado que el operador [] podría insertar un nuevo elemento en el contenedor, no es posible que sea una función miembro 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. Estrictamente hablando, esta función de miembro es innecesaria: existe solo por conveniencia
fuente
Un operador de índice solo debe ser constante para un contenedor de solo lectura (que realmente no existe en STL per se).
Los operadores de índice no solo se utilizan para observar valores.
fuente
const
y otra noconst
, como por ejemplostd::vector
.Si declara que su variable miembro std :: map es mutable
mutable std::map<...> m_map;
puede usar las funciones miembro no constante de std :: map dentro de sus funciones miembro constante.
fuente
mutable
se puede utilizar para miembros comostd::mutex
, cachés y ayudantes de depuración. Si el mapa se va a utilizar como caché para acelerar unaconst
función "captadora" muy cara , entoncesmutable
es aceptable. Debe tener cuidado, pero no es una idea terrible por sí sola.