¿Cuál es el constructor predeterminado para el puntero de C ++?

Tengo un código como este:

class MapIndex { private: typedef std::map Container; Container mapM; public: void add(std::list& values) { if (values.empty()) // sanity check return; std::string s(*(values.begin())); values.erase(values.begin()); if (values.empty()) return; MapIndex *mi = mapM[s]; // add(values); } } 

La principal preocupación que tengo es si la expresión mapM [s] devolvería referencia al puntero NULL si se agrega un nuevo elemento al mapa.

Los documentos SGI dicen esto: data_type & operator [] (const key_type & k) Devuelve una referencia al objeto que está asociado con una tecla en particular. Si el mapa aún no contiene dicho objeto, el operador [] inserta el objeto predeterminado tipo_datos ().

Entonces, mi pregunta es si la inserción del objeto predeterminado tipo_datos () creará un puntero NULL, o podría crear un puntero no válido apuntando a algún lugar en la memoria.

Creará un puntero NULL (0), que es un puntero no válido de todos modos 🙂

Sí, debe ser un puntero cero (NULL) ya que los contenedores STL inicializarán por defecto los objetos cuando no estén almacenados explícitamente (es decir, accediendo a una clave inexistente en un mapa como lo está haciendo o redimensionando un vector a un tamaño mayor).

C ++ Standard, 8.5 párrafo 5 establece:

Para inicializar por defecto un objeto de tipo T significa:

  • Si T es un tipo de clase no POD (clase de cláusula), se llama al constructor predeterminado para T (y la inicialización está mal formada si T no tiene un constructor predeterminado accesible)
  • Si T es un tipo de matriz, cada elemento se inicializa por defecto
  • De lo contrario, el almacenamiento del objeto se inicializa en cero.

También debe tener en cuenta que la inicialización predeterminada es diferente a simplemente omitir el constructor. Cuando omite el constructor y simplemente declara un tipo simple obtendrá un valor indeterminado.

 int a; // not default constructed, will have random data int b = int(); // will be initialised to zero 

ACTUALIZACIÓN: Completé mi progtwig y esa misma línea que estaba preguntando está causando que se bloquee a veces, pero en una etapa posterior. El problema es que estoy creando un nuevo objeto sin cambiar el puntero almacenado en std :: map. Lo que realmente se necesita es referencia o puntero a ese puntero.

 MapIndex *mi = mapM[s]; // < - question about this line if (!mi) mi = new MapIndex(); mi->add(values); 

debe cambiarse a:

 MapIndex* &mi = mapM[s]; // < - question about this line if (!mi) mi = new MapIndex(); mi->add(values); 

Me sorprende que nadie se haya dado cuenta de esto.

La expresión data_type() evalúa como un objeto inicializado por defecto. En el caso de los tipos que no son POD, se invoca el constructor predeterminado, pero en el caso de los tipos de POD, como los punteros, la inicialización predeterminada es equivalente a la inicialización cero.

Entonces sí, puedes confiar en tu mapa creando un puntero NULL . Para una explicación, puede referirse a Inicializadores de Pseudo Constructor .

No estoy seguro sobre el locking, pero definitivamente la pérdida de memoria como esta statement

if (! mi) mi = nuevo MapIndex ();

siempre devuelve verdadero, porque el puntero mi no es referencia de lo que mapM tiene para el valor particular de s.

También evitaría usar punteros regulares y usar boost :: shared_ptr o algún otro puntero que libera memoria cuando se destruye. Esto permite llamar a mapM.clear () o borrar () que debe llamar a destructores de claves y valores almacenados en el mapa. Bueno, si el valor es POD, como su puntero, entonces no se llamará a ningún destructor a menos que se elimine manualmente mientras se itera a través de un mapa completo, lo que provocará pérdidas de memoria.