Похоже, вы создаете два списка инициализатора в примере выше. Временные {"hello", "stackoverflow"}
и std::initializer_list<std::string> a
.
В gcc списки инициализаторов {}
на самом деле являются временными массивами, время жизни которых заканчивается после полного оператора (если только они не связаны напрямую с std::initializer_list
, как в строке комментария в примере ниже).
Время жизни внутреннего массива первого списка заканчивается сразу после того, как возвращается конструктор a
, и поэтому массив a
теперь указывает на недопустимую память (gcc только копирует указатель). Вы можете проверить, что деструкторы std::string
вызываются до входа в цикл.
И когда вы зацикливаетесь, вы читаете неверную память.
Согласно последнему стандартному черновику (n3242), §18.9 / 1, списки инициализатора не могут быть даже скопированы таким образом (они не предоставляют конструктора с параметрами).
#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;
}
С gcc 4.5.0 я получаю
dtor
dtor
after a's construction