How do I capture a smart pointer in a lambda?

Just capture the variable by value and let the copy constructor and destructor worry about ownership semantics- that's what smart pointers are for.


A lambda (even one with a universal capture like [=]) only actually captures variables used within its definition. Since in your example, pointer is never used inside the lambda, it's not captured and thus when it goes out of scope, it's the last shared pointer referring to stored and free() is called.

If you want to capture pointer, you could force its use:

return [=](const char * delim) mutable -> const char *
{
  pointer;
  const char *b = strtok_r(stored, delim, &tmpstorage);
  stored = nullptr;
  return b;
};

However, this is rather hackish. You want your functor stateful and with nontrivial state management. To me, this is a strong indicator an actual named class (instead of a lambda) would be in order. 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));
}