Exemplo artificial, por causa da questão:
void MyClass::MyFunction( int x ) const
{
std::cout << m_map[x] << std::endl
}
Isso não será compilado, pois o operador [] não é constante.
Isso é lamentável, pois a sintaxe [] parece muito limpa. Em vez disso, tenho que fazer algo assim:
void MyClass::MyFunction( int x ) const
{
MyMap iter = m_map.find(x);
std::cout << iter->second << std::endl
}
Isso sempre me incomodou. Por que o operador [] não é constante?
operator[]
render se o elemento dado não existir?Respostas:
Para
std::map
estd::unordered_map
,operator[]
irá inserir o valor do índice no contêiner se ele não existir anteriormente. É um pouco não intuitivo, mas é assim que as coisas são.Uma vez que deve ter permissão para falhar e inserir um valor padrão, o operador não pode ser usado em uma
const
instância do contêiner.http://en.cppreference.com/w/cpp/container/map/operator_at
fonte
std::set
não temoperator[]
.std::vector
tem um operador de leitura[]
que éconst
.map
deve fazer o mesmo.Agora que com C ++ 11 você pode ter uma versão mais limpa usando at ()
void MyClass::MyFunction( int x ) const { std::cout << m_map.at(x) << std::endl; }
fonte
map
tiver const e não constat()
s - por que não o mesmo tambémoperator[]
? com a versão const não inserindo nada, mas sim jogando? (Ou retornando um opcional, quando std :: opcional o torna o padrão)at
vem em dois sabores é porque ele faz umreturn *this;
, e a única diferença entre as sobrecargas é oconst
-ness da referência retornada. Os efeitos reais de ambosat
são exatamente os mesmos (ou seja, nenhum efeito).Nota para novos leitores.
A pergunta original era sobre os contêineres STL (não especificamente sobre o std :: map)
Deve-se observar que há uma versão const do operador [] na maioria dos contêineres.
Acontece que std :: map e std :: set não têm uma versão const e isso é o resultado da estrutura subjacente que os implementa.
De std :: vector
reference operator[](size_type n) const_reference operator[](size_type n) const
Além disso, para o seu segundo exemplo, você deve verificar se não foi possível encontrar o elemento.
void MyClass::MyFunction( int x ) const { MyMap iter = m_map.find(x); if (iter != m_map.end()) { std::cout << iter->second << std::endl } }
fonte
std::set
não temoperator[]
nada.Visto que operator [] pode inserir um novo elemento no contêiner, não pode ser uma função-membro const. Observe que a definição de operador [] é extremamente simples: m [k] é equivalente a (* ((m.insert (value_type (k, data_type ()))). First)). Second. Estritamente falando, esta função de membro é desnecessária: ela existe apenas por conveniência
fonte
Um operador de índice deve ser const apenas para um contêiner somente leitura (que realmente não existe no STL per se).
Os operadores de índice não são usados apenas para ver os valores.
fonte
const
, outra nãoconst
- como, por exemplo,std::vector
tem.Se você declarar sua variável de membro std :: map como mutável
mutable std::map<...> m_map;
você pode usar as funções-membro não const de std :: map dentro de suas funções-membro const.
fonte
mutable
pode ser usado para membros comostd::mutex
caches e auxiliares de depuração. Se o mapa for usado como um cache para acelerar umaconst
função "getter" muito cara , entãomutable
é aceitável. Você precisa ter cuidado, mas não é uma ideia terrível por si só.