在 c++11 模式下使用带有仅移动参数的 QtConcurrent::run
Posted
技术标签:
【中文标题】在 c++11 模式下使用带有仅移动参数的 QtConcurrent::run【英文标题】:Use QtConcurrent::run with move only argument in c++11 mode 【发布时间】:2018-03-11 20:30:24 【问题描述】:我想传递仅移动类型(std::unique_ptr
仅用于最简短的示例),
我想在 Qt 线程池中执行的功能,
但是这样的代码给出了编译时错误:
#include <QtConcurrent>
#include <memory>
void f(std::unique_ptr<int>)
int main()
std::unique_ptr<int> pnew int5;
QtConcurrent::run(f, std::move(p));
编译器抱怨这样的函数(Qt QtConcurrent/qtconcurrentrun.h
的一部分):
template <typename T, typename Param1, typename Arg1>
QFuture<T> run(T (*functionPointer)(Param1), const Arg1 &arg1)
return (new StoredFunctorCall1<T, T (*)(Param1), Arg1>(functionPointer, arg1))->start();
需要std::unique_ptr<_Tp, _Dp>::unique_ptr(const std::unique_ptr<_Tp, _Dp>&) [с _Tp = int; _Dp = std::default_delete<int>]
,换句话说,它使用复制而不是移动。
我只使用 C++11,对于接受 Function
的其他 Qt 函数,例如 QObject::connect
,我使用 std::bind
技巧:
std::bind([](const std::unique_ptr<int> &arg) , std::move(param));
但由于某种原因,这样的代码也无法编译:
std::unique_ptr<int> pnew int5;
auto func = std::bind([](std::unique_ptr<int>& a)
//call f here
, std::move(p));
QtConcurrent::run(func);
还抱怨删除 std::unique_ptr
的复制构造函数。
我当然可以用std::shared_ptr/QSharedPointer
解决它,
但可能是一些没有额外内存分配的建议方式?
【问题讨论】:
尝试将调用封装在 lambda 中,而不是使用std::bind
,例如 auto wrapper = [&p]() -> void f(std::move(p)); ;
。
@bnaecker 嗯,所以您建议参考“堆栈”变量,并在退出函数后使用此引用在另一个线程中堆栈,这是未定义的行为吗?
这里的例子中,函数在main()
结束之前被调用、运行和返回,所以没有悬空指针。如果您确实想在当前作用域结束后保留函数和指针,那么您当然需要将对象保留在堆上,无论您使用 lambda 还是 std::bind
。
【参考方案1】:
遗憾的是,QtConcurrent 还不支持移动语义。
主要的解决方法是做std::auto_ptr
所做的事情:在包装器中移动副本。很难,但在将移动支持添加到 Qt 并发之前没有其他方法。不过,修补起来并不是什么特别困难的事情。
【讨论】:
我倾向于成为一个 Qt 粉丝,但 QtConcurrent 真的令人失望。以上是关于在 c++11 模式下使用带有仅移动参数的 QtConcurrent::run的主要内容,如果未能解决你的问题,请参考以下文章
如何在仅预测模式下运行 Matlab 的卡尔曼滤波器(DSP 工具箱)?