【发布时间】:2017-12-17 11:01:30
【问题描述】:
基本上,我正在尝试创建一个 lambda,它捕获一个只能移动的对象(例如 unique_ptr),并将一些参数作为输入。
我有一个由回调引发的昂贵资源,我需要将其移动到另一个线程进行处理。该对象只能移动(并且这不能更改)并且回调签名按值获取它(可以更改为右值引用)。以下是状态问题的最小工作示例:
void processor(std::function<void(int)> func)
{
auto thread = std::async(std::launch::async, func, 2);
}
using ResourceType = std::unique_ptr<int>; //Example for moveable only type
void handler(ResourceType r)
{
processor([r](int x) // error C2280: ...unique_ptr...: attempting to reference a deleted function
{
int usage_of_resource = *r + x;
std::cout << usage_of_resource << std::endl;
});
}
我尝试关注这个问题和答案 (How to capture a unique_ptr into a lambda expression?) 但是,我不能使用 C++14,建议的答案甚至没有编译。 这是我尝试过的:
std::function<void(int)> getAction(ResourceType p)
{
return std::bind([](ResourceType& r, int x)
{
int usage_of_resource = *r + x;
std::cout << usage_of_resource << std::endl;
}, std::move(p), std::placeholders::_1);
}
void handler(ResourceType r)
{
processor(getAction(std::move(r)));
}
g++: 错误:使用已删除的函数
msvc:错误:试图引用已删除的函数
我尝试创建自己的 lambda(使用 struct 和 operator()),但我未能解决同样的问题。最终,作为一种解决方法,我创建了一个指向我的资源的新指针,并在调用处理器之前将它移到那里,然后在我传递的 lambda 中提取它。
这是仅在 C++14 中解决的 C++ 标准的真正问题吗?还是有办法以某种方式移动对象(当然最好是优雅的)?
编辑:
捕获底层资源可能会导致内存泄漏,因为处理器是一个固定大小的消息队列,当队列已满并且有新元素到达时,它会丢弃第一个元素(出队)。因此,在捕获时间和使用时间之间,可以丢弃 lambda,因此不会释放资源。
【问题讨论】:
-
问题似乎在于 std::bind 返回的对象如果包含
std::unique_ptr则不可移动(也不可复制)。我不知道为什么。 -
std::function<void(int)>应该是 CopyConstructible。