Qual é a maneira correta de inicializar um mapa estático? Precisamos de uma função estática que a inicialize?
447
Usando C ++ 11:
#include <map>
using namespace std;
map<int, char> m = {{1, 'a'}, {3, 'b'}, {5, 'c'}, {7, 'd'}};
Usando o Boost.Assign :
#include <map>
#include "boost/assign.hpp"
using namespace std;
using namespace boost::assign;
map<int, char> m = map_list_of (1, 'a') (3, 'b') (5, 'c') (7, 'd');
A melhor maneira é usar uma função:
fonte
extern
As variáveis não terão seus valores corretos neste "antes do construtor principal em tempo de execução" se o compilador apenas viu aextern
declaração, mas ainda não executou a definição de variável real .const map<int,int> m = create_map()
(e, portanto, inicialize os membros const de uma classe na lista de inicialização:struct MyClass {const map<int, int> m; MyClass(); }; MyClass::MyClass() : m(create_map())
Não é uma questão complicada fazer algo semelhante para impulsionar. Aqui está uma classe com apenas três funções, incluindo o construtor, para replicar o que o impulso fez (quase).
Uso:
O código acima funciona melhor para a inicialização de variáveis globais ou membros estáticos de uma classe que precisa ser inicializada e você não tem idéia de quando é usado primeiro, mas deseja garantir que os valores estejam disponíveis nele.
Se você diz, você precisa inserir elementos em um std :: map existente ... aqui está outra classe para você.
Uso:
Veja em ação com o GCC 4.7.2 aqui: http://ideone.com/3uYJiH
############### TUDO ABAIXO ESTE É OBSOLETO #################
EDIT : A
map_add_values
classe abaixo, que foi a solução original que eu sugeri, falharia quando se trata do GCC 4.5+. Veja o código acima para saber como adicionar valores ao mapa existente.Uso:
NOTA: Anteriormente, usei a
operator []
para adicionar os valores reais. Isso não é possível, como comentado por dalle.##################### FIM DA SEÇÃO OBSOLETA ######################
fonte
operator[]
leva apenas um único argumento.error: conflicting declaration ‘map_add_values<int, int> my_map’
error: ‘my_map’ has a previous declaration as ‘std::map<int, int> my_map’
Aqui está outra maneira que usa o construtor de dados de 2 elementos. Nenhuma função é necessária para inicializá-lo. Não há código de terceiros (Boost), funções ou objetos estáticos, truques, apenas C ++ simples:
Desde que escrevi esta resposta, o C ++ 11 está fora. Agora você pode inicializar diretamente os contêineres STL usando o novo recurso de lista de inicializadores:
fonte
Por exemplo:
Se o mapa for um membro de dados de uma classe, você poderá inicializá-lo diretamente no cabeçalho da seguinte maneira (desde C ++ 17):
fonte
Eu envolvia o mapa dentro de um objeto estático e colocava o código de inicialização do mapa no construtor desse objeto. Dessa forma, você tem certeza de que o mapa é criado antes da execução do código de inicialização.
fonte
Só queria compartilhar uma solução C ++ 98 pura:
fonte
Podes tentar:
fonte
{1, 2}
vez destd::pair<int, int>(1, 2)
.É semelhante a
PierreBdR
, sem copiar o mapa.fonte
Se você está preso ao C ++ 98 e não deseja usar o boost, aqui está a solução que eu uso quando preciso inicializar um mapa estático:
fonte
Você tem algumas respostas muito boas aqui, mas eu sou para mim, parece um caso de "quando tudo que você sabe é um martelo" ...
A resposta mais simples de por que não existe uma maneira padrão de inicializar um mapa estático, não há uma boa razão para usar um mapa estático ...
Um mapa é uma estrutura projetada para pesquisa rápida, de um conjunto desconhecido de elementos. Se você conhece os elementos com antecedência, basta usar uma matriz C. Digite os valores de maneira ordenada ou execute uma classificação neles, se você não puder fazer isso. Você pode obter o desempenho do log (n) usando as funções stl :: para efetuar loop-up de entradas, lower_bound / upper_bound. Quando eu testei isso anteriormente, eles normalmente executam pelo menos 4 vezes mais rápido que um mapa.
As vantagens são muitas vezes ... - desempenho mais rápido (* 4, eu medi em muitos tipos de CPU, é sempre em torno de 4) - depuração mais simples. É mais fácil ver o que está acontecendo com um layout linear. - Implementações triviais de operações de cópia, caso isso seja necessário. - Ele não aloca memória no tempo de execução, portanto, nunca lançará uma exceção. - É uma interface padrão e, portanto, é muito fácil compartilhar entre DLLs ou idiomas, etc.
Eu poderia continuar, mas se você quiser mais, por que não olhar para os muitos blogs da Stroustrup sobre o assunto.
fonte
map
também é uma forma útil para representar uma função parcial (função no sentido matemático; mas também, mais ou menos, no sentido de programação). Uma matriz não faz isso. Você não pode, por exemplo, pesquisar dados de uma matriz usando uma string.