2012-06-07 12 views
12

Sto provando a inizializzare una mappa STL usando la sintassi C++ 11 ma sembra non funzionare. Dopo l'inizializzazione, quando provo ad accedere all'elemento, tenta di chiamare il costruttore privato di Foo. Ho dimenticato qualcosa? Funziona se uso a. Mi chiedevo se potevo usare operatore [] per accedere valori inizializzati ...C++ 11 initialize map

#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; 
} 

risposta

21

Quando si utilizza il operator[] su una mappa, è possibile utilizzare l'operatore sia per ottenere un valore dalla mappa o assegnare un valore alla mappa. Per assegnare il valore alla mappa, la mappa deve costruire un oggetto del suo tipo di valore e restituirlo per riferimento, in modo da poter utilizzare operator= per sovrascrivere un oggetto esistente.

Di conseguenza, il tipo deve essere predefinito come costruibile in modo che sia possibile creare un nuovo oggetto per l'utente da assegnare.

In fase di esecuzione, il costruttore non verrà chiamato se la chiave esiste già, ma il compilatore non ha modo di sapere se si utilizzerà mai operator[] per accedere a un valore che non esiste, quindi richiede il costruttore per essere pubblico.

+0

Grazie per la chiara spiegazione. –

18

operator[] della mappa richiede il tipo di essere costruibile di default, perché crea una nuova voce, se uno non esiste.

È possibile utilizzare at() invece, che getta se la voce non esiste:

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

Il fatto che richieda l'esistenza del costruttore non significa che debba chiamarlo se l'oggetto esiste già, cosa che non dovrebbe. –

+3

@ DavidRodríguez-dribeas ma il codice morto deve ancora essere compilato. –

+5

@David: C++ 11 richiede infatti il ​​concetto 'DefaultConstructible' per' map <> :: operator [] '(§23.4.4.3/2.6). – ildjarn