在 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&lt;_Tp, _Dp&gt;::unique_ptr(const std::unique_ptr&lt;_Tp, _Dp&gt;&amp;) [с _Tp = int; _Dp = std::default_delete&lt;int&gt;],换句话说,它使用复制而不是移动。

我只使用 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 = [&amp;p]() -&gt; void f(std::move(p)); ; @bnaecker 嗯,所以您建议参考“堆栈”变量,并在退出函数后使用此引用在另一个线程中堆栈,这是未定义的行为吗? 这里的例子中,函数在main()结束之前被调用、运行和返回,所以没有悬空指针。如果您确实想在当前作用域结束后保留​​函数和指针,那么您当然需要将对象保留在堆上,无论您使用 lambda 还是 std::bind 【参考方案1】:

遗憾的是,QtConcurrent 还不支持移动语义。

主要的解决方法是做std::auto_ptr 所做的事情:在包装器中移动副本。很难,但在将移动支持添加到 Qt 并发之前没有其他方法。不过,修补起来并不是什么特别困难的事情。

【讨论】:

我倾向于成为一个 Qt 粉丝,但 QtConcurrent 真的令人失望。

以上是关于在 c++11 模式下使用带有仅移动参数的 QtConcurrent::run的主要内容,如果未能解决你的问题,请参考以下文章

定时器仅在调试模式下工作

移动模式我没有获得带有关闭按钮的全宽菜单

具有非内联汇编的 Qt C++ 项目

如何在仅预测模式下运行 Matlab 的卡尔曼滤波器(DSP 工具箱)?

Windows 窗体应用程序 C# - 在调试模式下运行后选项卡控件项移动位置

Firebase 消息传递仅在调试模式下工作,而不是在发布模式下工作 (iOS)