C ++ const map element access

100

Tentei usar o operador [] para acessar o elemento em um mapa const C ++, mas esse método falhou. Também tentei usar "at ()" para fazer a mesma coisa. Funcionou dessa vez. No entanto, não consegui encontrar nenhuma referência sobre o uso de "at ()" para acessar o elemento em um mapa const C ++. É "at ()" uma função recém-adicionada no mapa C ++? Onde posso encontrar mais informações sobre isso? Muito obrigado!

Um exemplo poderia ser o seguinte:

#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]", ele retornou os seguintes erros durante a compilação:

t01.cpp: 14: erro: passando 'const std :: map, std :: allocator>>' como 'este' argumento de '_Tp & std :: map <_Key, _Tp, _Compare, _Alloc> :: operator [] ( const _Key &) [with _Key = int, _Tp = char, _Compare = std :: less, _Alloc = std :: allocator>] 'descarta qualificadores

O compilador usado é g ++ 4.2.1

esfera de gelo
fonte

Respostas:

124

at()é um novo método std::mapem C ++ 11.

Em vez de inserir um novo elemento padrão construído como operator[]faria se um elemento com a chave fornecida não existisse, ele lança uma std::out_of_rangeexceção. (Isso é semelhante ao comportamento de at()para dequee vector.)

Por causa desse comportamento, faz sentido que haja uma constsobrecarga de at(), ao contrário da operator[]qual sempre tem potencial para alterar o mapa.

CB Bailey
fonte
É possível fazer com que "at" retorne um valor padrão em vez de lançar uma exceção?
user1202136
Estou usando at()no VS2013 em um projeto definido para usar o kit de ferramentas VS2010. Achei que isso significava que não estava usando C ++ 11 ... Mas ainda assim ele compila ... ??
thomthom
1
Só preciso comentar que não faz sentido omitir o operador const [], que também poderia lançar uma exceção para um elemento não mapeado em vez de alterar o mapa.
Spencer
@Spencer Seria surpreendente se as sobrecargas const e não const do operador [] tivessem efeitos diferentes. Normalmente, esperamos que, se alguns objetos não constantes ou referências em um programa forem transformados em const, o programa continuará a se comportar da mesma maneira, contanto que seja compilado. Permitir que apenas a sobrecarga não const lance exceções pode resultar em bugs que não são detectados até o tempo de execução.
Brian de
@Brian Você quis dizer "Permitindo que apenas a sobrecarga const lance exceções"?
Spencer
33

Se um elemento não existir em a map, o operator []adicionará - o que obviamente não pode funcionar em um constmapa, portanto C ++ não define uma constversão do operador. Este é um bom exemplo do verificador de tipo do compilador evitando um possível erro de tempo de execução.

No seu caso, você precisa usar o findque retornará um (iterador para o) elemento se ele existir, ele nunca modificará o map. Se um item não existir, ele retorna um iterador para o do mapa end().

atnão existe e nem deveria compilar. Talvez esta seja uma “extensão do compilador” (=um inseto novo em C ++ 0x).

Konrad Rudolph
fonte
O padrão C ++ proíbe a implementação de definir funções de membro não padrão adicionais em classes de biblioteca?
Tim Martin de
@Tim Eu acredito que a interface está fixa, sim.
Konrad Rudolph
4

O operador [] criará uma nova entrada no mapa se a chave fornecida não existir. Isso pode, portanto, mudar o mapa.

Veja este link .

vidstige
fonte