Inspecting an uninitialized object is an UB, in this case it'd been obscured by this string:
s2 = std::to_string(i);
It's a call to operator=
of std::string
for object stored at location of s2
.
It wasn't initialized at that point yet. I assume that you could fix it by initializing s2
, but it's not possible to do before constructor call in initialization list.
You cannot change order of creation, even if you write that section in wrong order. s2
always initialized after s1
, both done after constructor call but before entering its body. Thus the order looks like:
- Call of ctor
S(int)
with initialization of argument i
;
- Creation of lambda object, capturing
this
and i
- Call of operator() of lambda
- Call
operator=
of std::string
for object stored at location of s2
- Creation of
std::string
- Delegating call of ctor
S(std::string)
with argument s
with reference to created string.
- Initialization of
s1
with value of s
- Default initialization of
s2
Bullets 4. and 8. happen in order which isn't legal, even worse, due to implementation, it may not to yield an error, so gcc version likely writes that data into some random area of memory. MSVC, at least in debug version, may generate some diagnostic code, for standard doesn't define program behavior for such case.