A lambda (even one with a universal capture like [=] ) actually only captures the variables used in its definition. Since pointer never used inside a lambda in your example, it is not written, and therefore, when it goes out of scope, it is called by the last common pointer, referencing stored and free() .
If you want to capture pointer , you can force it to use:
return [=](const char * delim) mutable -> const char * { pointer; const char *b = strtok_r(stored, delim, &tmpstorage); stored = nullptr; return b; };
However, these are pretty hacks. You want your functor to be efficient and with non-trivial government. For me, this is a strong indicator, and the actual named class (and not lambda) will be fine. So I would change it like this:
std::function<const char *(const char *)> test(const char *input) { struct Tokenizer { std::shared_ptr<char> pointer; char* stored; char* tmpstorage; explicit Tokenizer(char* stored) : pointer(stored, free), stored(stored), tmpstorage(nullptr) {} const char* operator() (const char * delim) { const char *b = strtok_r(stored, delim, &tmpstorage); stored = nullptr; return b; } }; return Tokenizer(strdup(input)); }
source share