【问题标题】:C++ `std::move` custom type into a lambda captureC++ `std::move` 自定义类型转换为 lambda 捕获
【发布时间】:2020-08-17 12:51:19
【问题描述】:

我有一个类,我在其中删除了复制赋值运算符和复制构造函数,只留下了移动赋值运算符和移动构造函数。例如:

struct Number {
  public:
  int *pNum;

  Number &operator=(const Number &rhs) = delete;
  Number(const Number &rhs) = delete;

  Number &operator=(Number &&rhs) {
    if (&rhs == this) {
      return *this;
    }

    pNum = rhs.pNum;
    rhs.pNum = nullptr;
    return *this;
  }

  Number() = default;

  Number(Number &&rhs) {
    *this = std::move(rhs);
  }

  ~Number() {
    delete pNum;
  }
};

现在,我想使用 std::move 将此类捕获到 lambda 中。例如:

int main() {
  std::function<int(int)> add;


  int a = 3;

  {

    Number n{};
    n.pNum = new int;
    *n.pNum = 5;

    add = [&, capA{std::move(n)}](int) mutable -> int {
      int b = *capA.pNum; // 5
      return a + b; // 8
    };
  }

  std::cout << add(3);
}

但是,n 似乎是const,因此 c++ 会尝试使用已删除的复制构造函数。我将如何解决这个问题? (回复:https://repl.it/@25GrantY/WeirdLambda

【问题讨论】:

    标签: c++ lambda


    【解决方案1】:

    问题不在于 lambda。例如。这行得通:

    auto l = [&, capA{std::move(n)}](int) mutable -> int {
          int b = *capA.pNum; // 5
          return a + b; // 8
        };
    

    问题在于std::function 和这个 lambda。因为您捕获了一个不可复制的对象,所以 lambda 是不可复制的。 std::function 要求其存储的对象是可复制的,这就是它不起作用的原因。

    您可以在这里阅读更多内容:Move-only version of std::function

    【讨论】:

      【解决方案2】:

      这里的问题来自 std::function。 根据文档,此类必须满足 CopyConstructible 和 CopyAssignable 要求。 https://en.cppreference.com/w/cpp/utility/functional/function

      std::function 满足 CopyConstructible 和 可复制。

      当您尝试使用按值捕获仅移动类型的 lambda 初始化 std::function 时,此类分配(如果成功)将违反上述两个要求。

      这就是编译失败并出现错误的原因。

      如何解决这个问题?

      要么不使用 std::function,要么让你的 lambda 可复制。

      您可以使用 std::shared_ptr 作为仅移动类型的可复制包装器。

      auto shared_number = std::make_shared<Number>{};
      

      现在,您可以将 shared_number 传递给 lambda,并分配给 std::function。

      【讨论】:

        猜你喜欢
        • 2019-03-05
        • 2020-05-29
        • 2011-03-31
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-01-22
        • 2015-11-27
        相关资源
        最近更新 更多