为什么我不能在C ++ 14中移动lambda中的std :: unique_ptr?

时间:2015-05-29 11:19:00

标签: c++ lambda c++14 move-semantics

我想在lambda中传递一个原始指针,但如果没有调用lambda,我不希望它被泄露。它看起来像这样:

void Clean(std::unique_ptr<int>&& list);

void f(int* list) {
  thread_pool.Push([list = std::unique_ptr<int>(list) ] {
    Clean(std::move(list));  // <-- here is an error.
  });
}

我在Clang 3.7.0中遇到错误:

  

错误:对类型'unique_ptr&lt; [2 * ...]&gt;'的引用绑定到'unique_ptr&lt; [2 * ...]&gt;'类型的值掉落资格赛

但我没有看到任何限定词,尤其是掉线。

另外,我在邮件列表上找到了类似的report,但没有回答。

我应该如何修改我的代码,以便编译并按语义按预期工作?

1 个答案:

答案 0 :(得分:27)

你需要制作内部lambda mutable

[this](Pointer* list) {
  thread_pool.Push([this, list = std::unique_ptr<int>(list) ]() mutable {
                                                               ^^^^^^^^^
    Clean(std::move(list));
  });
};
lambdas上的

operator()默认为const,因此您无法在该调用中修改其成员。因此,内部list的行为就像const std::unique_ptr<int>一样。当您执行move演员表时,它会转换为const std::unique_ptr<int>&&。这就是为什么你得到关于删除限定符的编译错误的原因:你试图将 const rvalue引用转换为非const rvalue引用。该错误可能没有那么有用,但这一切都归结为:您不能move const unique_ptr

mutable修正了 - operator()不再是const,因此该问题不再适用。

注意:如果您的Clean()采用unique_ptr<int>代替unique_ptr<int>&&,这更有意义(因为它更明确,确定性下沉),那么错误就会出现更加明显:

error: call to deleted constructor of `std::unique_ptr<int>`
note: 'unique_ptr' has been explicitly marked deleted here  

    unique_ptr(const unique_ptr&) = delete
    ^