我想在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中收到错误:



但是我没有看到任何预选赛,特别是弃权赛。

另外,我在邮件列表中发现了类似的report,但没有答案。

我应该如何修改我的代码,使其能够按语义期望地进行编译和工作?

最佳答案

您需要将内部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引用。该错误可能没有得到应有的帮助,但最终可以归结为:您无法moveconst 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
    ^

关于c++ - 为什么我不能在C++ 14的lambda中 move std::unique_ptr?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/30528242/

10-11 23:08
查看更多