我想在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 <[2 * ...]>'的引用绑定到类型'unique_ptr <[2 * ...]>'的值会丢弃限定符
但是我没有看到任何限定词,尤其是掉线。
此外,我在邮件列表上找到了类似的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引用。这个错误可能没有那么有用,但这一切归结为:你不能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
^