c++ - 如何在 lambda 中捕获智能指针?

标签 c++ smart-pointers lambda

在 lambda 中捕获智能指针的最佳方法是什么?我的一次尝试导致了释放后使用错误。

示例代码:

#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;
  };
}

失败,如 AddressSanitizer 所示。

最佳答案

lambda(即使是像 [=] 这样具有通用捕获的 lambda)实际上只捕获其定义中使用的变量。由于在您的示例中,pointer 从未在 lambda 内部使用,因此不会被捕获,因此当它超出范围时,它是引用 storedfree() 被调用。

如果你想捕获指针,你可以强制使用它:

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

然而,这是相当骇人听闻的。你希望你的仿函数有状态并且具有非平凡的状态管理。对我来说,这是一个强有力的指标,一个实际的命名类(而不是 lambda)将是有序的。所以我会这样改变它:

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));
}

关于c++ - 如何在 lambda 中捕获智能指针?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20675422/

相关文章:

c++ - D3D11 : E_OUTOFMEMORY when mapping vertex buffer

c++ - 当我不关心顺序并且没有重复项时,更快的删除删除习惯用法?

C++ - 使用引用计数的基本垃圾收集器

c++ - 存在 lambda 参数时 ADL 失败?

java - 方法引用没有被延迟评估?

java - 公共(public)静态最终 Lambda?

c++ - 使用 MSVC 将 C 源文件编译为 C++

c++ - 如何在 OpenGL 中为屏幕上的给定像素找到对应的图元或顶点

c++ - 智能指针无法释放内存

c++ - unique_ptr 删除器开销