2009-09-25 14 views
70

wymyślony przykład, ze względu na pytanie:Dlaczego nie jest ustawieniem operatora [] dla map STL?

void MyClass::MyFunction(int x) const 
{ 
    std::cout << m_map[x] << std::endl 
} 

nie będzie zestawiania, gdyż [] operator const.

To niefortunne, ponieważ składnia [] wygląda bardzo czysto. Zamiast tego muszę zrobić coś takiego:

void MyClass::MyFunction(int x) const 
{ 
    MyMap iter = m_map.find(x); 
    std::cout << iter->second << std::endl 
} 

To zawsze mnie wkurzało. Dlaczego operator [] nie jest const?

+4

co powinno operatora '[]' wydajność w przypadku dany element nie istnieje? –

+1

@Frerich Raabe: To samo, co funkcja at member: throw std :: out_of_range –

Odpowiedz

76

Dla std::map, operator[] wstawi wartość indeksu do pojemnika, jeśli nie wcześniej istnieć. To trochę nieintuicyjne, ale tak właśnie jest.

Ponieważ należy zezwolić na niepowodzenie i wstawić wartość domyślną, operator nie może być używany w instancji kontenera const.

http://en.cppreference.com/w/cpp/container/map/operator_at

+1

'std :: set' nie ma operatora' []. – avakar

+0

Ups, to prawda. Edytowane. – Alan

+0

To jest właściwa odpowiedź, ale wersja const może zrobić to samo, co członek "at". To jest rzut std :: out_of_range ... –

0

Operator indeksu powinien być stały tylko dla kontenera tylko do odczytu (który tak naprawdę nie istnieje w STL per se).

Operatory indeksów są używane nie tylko do przeglądania wartości.

+4

Pytanie brzmi: dlaczego nie ma dwóch przeciążonych wersji - jedna 'const', inna nie-' konstancja '- jak np. 'std :: vector' robi. –

26

Uwaga dla nowych czytelników.
Oryginalny pytanie dotyczyło kontenerów STL (nie konkretnie o std :: map)

Należy zauważyć, że jest to wersja const operator [] na większości pojemników.
Po prostu std :: map i std :: set nie mają wersji const, a to jest wynikiem podstawowej struktury, która je implementuje.

Od std :: vector

reference  operator[](size_type n) 
const_reference operator[](size_type n) const 

także dla drugiego przykładu należy sprawdzić awarii wybrać element.

void MyClass::MyFunction(int x) const 
{ 
    MyMap iter = m_map.find(x); 
    if (iter != m_map.end()) 
    { 
     std::cout << iter->second << std::endl 
    } 
} 
+0

'std :: set' nie ma w ogóle' operatora [] '. – Everyone

0

Jeśli zadeklarować swoją zmienną składową std :: map być zmienny

mutable std::map<...> m_map; 

można użyć const funkcji Członka std :: map w twoich const funkcji składowych.

+13

To jednak straszny pomysł. – GManNickG

+0

Dlaczego to jest okropny pomysł? –

+6

Interfejs API dla twojej klasy leży, jeśli to zrobisz. Funkcja twierdzi, że jest const - co oznacza, że ​​nie zmodyfikuje żadnych zmiennych składowych - ale w rzeczywistości może to modyfikować element danych m_map. – Runcible

3

Ponieważ operator [] może wstawić nowy element do kontenera, nie może to być funkcja z elementem stałym. Zauważ, że definicja operatora [] jest niezwykle prosta: m [k] jest równoważne (* (()sert (value_type (k, data_type()))) first)) second. Ściśle mówiąc, ta funkcja jest niepotrzebna członkiem: istnieje tylko dla wygody

41

Teraz, z C++ 11 można mieć czystszą wersję przy użyciu at()

void MyClass::MyFunction(int x) const 
{ 
    std::cout << m_map.at(x) << std::endl; 
} 
+3

Jeśli 'map' ma const i non const' at() 's - dlaczego nie to samo również dla' operator [] '? z wersją Const nie wstawiającą nic, ale rzucanie? (Lub zwraca opcjonalny, gdy std :: optional czyni go standardem) – einpoklum

+0

@einpoklum Punktem stałej stałości jest głównie statyczna kontrola kompilacji. Wolałbym, aby kompilator narzekał, niż rzucić wyjątek, ponieważ nie użyłem poprawnie obiektów const. –

Powiązane problemy