Jaki jest właściwy sposób inicjowania mapy statycznej? Czy potrzebujemy funkcji statycznej, która ją zainicjuje?
448
Za pomocą C ++ 11:
#include <map>
using namespace std;
map<int, char> m = {{1, 'a'}, {3, 'b'}, {5, 'c'}, {7, 'd'}};
Za pomocą 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');
Najlepszym sposobem jest użycie funkcji:
źródło
extern
zmienne nie będą miały poprawnych wartości w tym „przed głównym konstruktorem czasu wykonywania”, jeśli kompilator zobaczył tylkoextern
deklarację, ale nie natrafił jeszcze na rzeczywistą definicję zmiennej .const map<int,int> m = create_map()
(a więc, zainicjowania stałych elementów klasy na liście inicjalizacji:struct MyClass {const map<int, int> m; MyClass(); }; MyClass::MyClass() : m(create_map())
Stworzenie czegoś podobnego do ulepszenia nie jest skomplikowane. Oto klasa z trzema funkcjami, w tym konstruktorem, do replikacji tego, co zrobiło boost (prawie).
Stosowanie:
Powyższy kod działa najlepiej do inicjowania zmiennych globalnych lub statycznych elementów klasy, które należy zainicjować i nie masz pojęcia, kiedy zostanie najpierw użyty, ale chcesz się upewnić, że wartości są w nim dostępne.
Jeśli powiedzmy, musisz wstawić elementy do istniejącej std :: map ... oto kolejna klasa dla Ciebie.
Stosowanie:
Zobacz to w działaniu z GCC 4.7.2 tutaj: http://ideone.com/3uYJiH
############### WSZYSTKO PONIŻEJ TO JEST OBSOLETE ###################
EDYCJA : Poniższa
map_add_values
klasa, która była oryginalnym rozwiązaniem, które zasugerowałem, zawiedzie, jeśli chodzi o GCC 4.5+. Zobacz powyższy kod, aby dowiedzieć się, jak dodać wartości do istniejącej mapy.Stosowanie:
UWAGA: Poprzednio użyłem a
operator []
do dodania rzeczywistych wartości. Nie jest to możliwe, jak komentuje dalle.###################### END OF OBSOLETE SECTION #############################
źródło
operator[]
bierze tylko jeden argument.error: conflicting declaration ‘map_add_values<int, int> my_map’
error: ‘my_map’ has a previous declaration as ‘std::map<int, int> my_map’
Oto inny sposób wykorzystania 2-elementowego konstruktora danych. Do inicjalizacji nie są potrzebne żadne funkcje. Nie ma kodu innej firmy (Boost), żadnych statycznych funkcji lub obiektów, żadnych sztuczek, po prostu prosty C ++:
Odkąd napisałem tę odpowiedź, C ++ 11 jest niedostępny. Możesz teraz bezpośrednio inicjalizować kontenery STL za pomocą nowej funkcji listy inicjalizacyjnej:
źródło
Na przykład:
Jeśli map jest członkiem danych klasy, możesz zainicjować go bezpośrednio w nagłówku w następujący sposób (od C ++ 17):
źródło
Owinąłbym mapę wewnątrz obiektu statycznego i umieściłem kod inicjalizacji mapy w konstruktorze tego obiektu, w ten sposób masz pewność, że mapa zostanie utworzona przed wykonaniem kodu inicjalizacji.
źródło
Chciałem po prostu podzielić się czystym obejściem C ++ 98:
źródło
Możesz spróbować:
źródło
{1, 2}
zamiaststd::pair<int, int>(1, 2)
.Jest to podobne do
PierreBdR
bez kopiowania mapy.źródło
Jeśli utknąłeś w C ++ 98 i nie chcesz używać boosta, oto rozwiązanie, którego używam, gdy muszę zainicjować mapę statyczną:
źródło
Masz tutaj bardzo dobre odpowiedzi, ale dla mnie wygląda to na przypadek „kiedy wszystko, co wiesz, to młot” ...
Najprostsza odpowiedź na pytanie, dlaczego nie ma standardowego sposobu inicjowania mapy statycznej, nie ma dobrego powodu, aby kiedykolwiek używać mapy statycznej ...
Mapa to struktura zaprojektowana do szybkiego wyszukiwania nieznanego zestawu elementów. Jeśli znasz elementy wcześniej, po prostu użyj tablicy C. Wprowadź wartości w sposób posortowany lub uruchom sortowanie na nich, jeśli nie możesz tego zrobić. Następnie można uzyskać wydajność dziennika (n), używając funkcji stl :: do zapętlania wpisów, dolna_możliwość / górna_możliwość. Kiedy testowałem to wcześniej, zwykle działają one co najmniej 4 razy szybciej niż mapa.
Korzyści są wiele razy ... - szybsza wydajność (* 4, zmierzyłem na wielu typach procesorów, zawsze około 4) - prostsze debugowanie. Po prostu łatwiej jest zobaczyć, co się dzieje z układem liniowym. - Trywialne wdrożenia operacji kopiowania, jeśli okaże się to konieczne. - Nie przydziela pamięci w czasie wykonywania, więc nigdy nie zgłasza wyjątku. - Jest to standardowy interfejs, dzięki czemu można go łatwo udostępniać w różnych bibliotekach DLL, językach itp.
Mógłbym kontynuować, ale jeśli chcesz więcej, spójrz na wiele blogów Stroustrup na ten temat.
źródło
map
jest także przydatną formą do reprezentowania funkcji częściowej (funkcja w sensie matematycznym; ale także swego rodzaju w sensie programowania). Tablica tego nie robi. Nie można, powiedzmy, wyszukiwać danych z tablicy za pomocą łańcucha.