2012-06-07 16 views
12

Estoy tratando de inicializar un mapa STL usando la sintaxis C++ 11 pero eso no parece funcionar. Después de la inicialización, cuando intento acceder al elemento, intenta llamar al constructor privado de Foo. ¿Me he perdido algo? Funciona si uso at. Me pregunto si podía usar el operador [] para acceder a los valores inicializados ...C++ 11 inicializar el mapa

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

Respuesta

21

Cuando se utiliza la operator[] en un mapa, puede utilizar el operador para obtener ya sea un valor en el mapa o asigna un valor en el mapa. Para asignar el valor al mapa, el mapa debe construir un objeto de su tipo de valor y devolverlo por referencia para que pueda usar operator= para sobrescribir un objeto existente.

En consecuencia, el tipo tiene que ser predecible de forma que se pueda crear un nuevo objeto para asignar.

En tiempo de ejecución, no se llamará al constructor si la clave ya existe, pero el compilador no tiene manera de saber si alguna vez usará operator[] para acceder a un valor que no existe, por lo que requiere el constructor para ser público.

+0

Gracias por la clara explicación. –

18

operator[] del mapa requiere el tipo de ser construible por defecto, ya que crea una nueva entrada si no existe uno.

Puede utilizar at() lugar, que lanza si la entrada no existe:

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

El hecho de que exija que el constructor exista no significa que deba llamarlo si el objeto ya existe, lo cual no debería ser. –

+3

@ DavidRodríguez-dribeas pero aún tiene que compilarse el código muerto. –

+5

@David: C++ 11 requiere el concepto 'DefaultConstructible' para' map <> :: operator [] '(§23.4.4.3/2,6). – ildjarn