Parece que va a crear dos listas de inicializador en el ejemplo anterior. Temporal {"hello", "stackoverflow"}
y std::initializer_list<std::string> a
.
En gcc, {}
las listas de inicializadores son en realidad matrices temporales cuya duración termina después de la instrucción completa (a menos que se vincule directamente a std::initializer_list
como en la línea comentada en el ejemplo a continuación).
La vida útil de la matriz interna de la primera lista finaliza justo después de que el constructor a
regrese y, por lo tanto, la matriz a
apunta a la memoria no válida (gcc solo copia el puntero). Puede verificar que se llame a los destructores std::string
antes de ingresar al ciclo.
Y cuando llega al bucle, está leyendo memoria no válida.
Según el último borrador estándar (n3242), §18.9/1, las listas de inicializadores ni siquiera se pueden copiar así (no proporcionan ningún constructor con parámetros).
#include <initializer_list>
#include <iostream>
class A
{
public:
A(int)
{ }
~A()
{
std::cout << "dtor" << std::endl;
}
};
int main()
{
std::initializer_list<A> a({A(2), A(3)});
// vs std::initializer_list<A> a{A(2), A(3)};
std::cout << "after a's construction" << std::endl;
}
con GCC 4.5.0, consigo
dtor
dtor
after a's construction
Esto imprime la cadena ' "hola"' demasiado: http://ideone.com/C9Q7p -.- –
@Johannes: Si eliminar 'c_str()', no imprime '" hello "': http://ideone.com/NTRUh ... y estoy confundido. ¿Qué tiene de malo? – Nawaz
Es porque estás trabajando con referencia a la variable local (que sale del alcance cuando la función vuelve). Cuando usas c_str(), tienes suerte (o desafortunadamente, dependiendo del punto de vista) de que la memoria todavía contiene referencia a la cadena 'char *' y que el área del montón todavía no se ha sobrescrito. :) – Vitus