How to capture smart pointer in lambda?

What is the best way to capture smart pointer in lambda? One of my attempts led to an error after use.

Code example:

#include <cstring> #include <functional> #include <memory> #include <iostream> std::function<const char *(const char *)> test(const char *input); int main() { std::cout.sync_with_stdio(false); std::function<const char *(const char *)> a = test("I love you"); const char *c; while ((c = a(" "))){ std::cout << c << std::endl; } return 0; } std::function<const char *(const char *)> test(const char *input) { char* stored = strdup(input); char *tmpstorage = nullptr; std::shared_ptr<char> pointer = std::shared_ptr<char>(stored, free); return [=](const char * delim) mutable -> const char * { const char *b = strtok_r(stored, delim, &tmpstorage); stored = nullptr; return b; }; } 

not working as shown in AddressSanitizer.

+6
source share
2 answers

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)); } 
+4
source

Just write down the variable by value and let the copy constructor and destructor worry about the semantics of ownership - about which smart pointers.

+3
source

All Articles