Проверка неинициализированного объекта - это UB, в данном случае он был скрыт этой строкой:
s2 = std::to_string(i);
Это вызов operator=
из std::string
для объекта, хранящегося в местоположении s2
.Это еще не было инициализировано.Я предполагаю, что вы могли бы это исправить, инициализировав s2
, но это невозможно сделать до вызова конструктора в списке инициализации.
Вы не можете изменить порядок создания, даже если вы напишите этот раздел в неправильном порядке.s2
всегда инициализируется после s1
, оба выполняются после вызова конструктора, но до ввода его тела.Таким образом, порядок выглядит так:
- Вызов ctor
S(int)
с инициализацией аргумента i
; - Создание лямбда-объекта, захват
this
и i
- Вызов оператора () лямбды
- Вызов
operator=
из std::string
для объекта, хранящегося в местоположении s2
- Создание
std::string
- Делегирование вызова ctor
S(std::string)
с аргументом s
со ссылкой на созданную строку. - Инициализация
s1
со значением s
- Инициализация по умолчанию
s2
Маркеры 4. и 8. выполняются в том порядке, который недопустим, даже хуже, из-за реализации он может не выдавать ошибку, поэтомуВерсия gcc, вероятно, записывает эти данные в какую-то случайную область памяти.MSVC, по крайней мере в отладочной версии, может генерировать некоторый диагностический код, поскольку стандарт не определяет поведение программы в этом случае.