2012-06-07 24 views
12

Próbuję zainicjować mapę STL przy użyciu składni C++ 11, ale to nie wydaje się działać. Po inicjalizacji, kiedy próbuję uzyskać dostęp do elementu, próbuje wywołać prywatnego konstruktora Foo. Przegapiłem coś? Działa, jeśli używam w. Zastanawiam się, czy mogę użyć operatora [], aby uzyskać dostęp do wartości zainicjowany ...zainicjować mapę C++ 11

#include <map> 
#include <string> 

class Foo{ 
public: 
    int a, b; 
    Foo(int a_, int b_){ 
     a = a_; 
     b = b_; 
    } 

private: 
    Foo(){}; 
}; 


int main(){ 

    std::map<std::string, Foo> myMap = { {"1", Foo(10,5)}, {"2", Foo(5,10)} }; 
    int b = myMap["1"].b; // it tries to call private constructor of Foo. 
    return 0; 
} 

Odpowiedz

21

Podczas korzystania z operator[] na mapie, można użyć operatora albo uzyskać wartość z mapy lub przypisz wartość do mapy. Aby przypisać wartość do mapy, mapa musi skonstruować obiekt o jego typie wartości i zwrócić go przez odniesienie, aby można było użyć operator=, aby nadpisać istniejący obiekt.

W konsekwencji typ musi być domyślnie skonstruowany, aby można było utworzyć nowy obiekt, do którego można przypisać.

W czasie wykonywania konstruktor nie zostanie wywołany, jeśli klucz już istnieje, ale kompilator nie ma możliwości sprawdzenia, czy kiedykolwiek użyjesz operator[] do uzyskania wartości, która nie istnieje, więc wymaga Konstruktor jest publiczny.

+0

Dziękuję za jasne wyjaśnienie. –

18

operator[] mapy wymaga typ być domyślnym constructible, ponieważ tworzy nowy wpis, jeśli nie istnieje.

Można użyć at() zamiast, który rzuca jeśli wpis nie istnieje:

int b = myMap.at("1").b; 
+0

Fakt, że wymaga on istnienia konstruktora, nie oznacza, że ​​powinien go wywoływać, jeśli obiekt już istnieje, a nie powinien. –

+3

@ DavidRodríguez-dribeas, ale martwy kod nadal musi się kompilować. –

+5

@David: C++ 11 rzeczywiście wymaga koncepcji 'DefaultConstructible' dla' map <> :: operator [] '(§23.4.4.3/2,6). – ildjarn