std::move 将 std::string 移动到另一个线程时出错

Posted

技术标签:

【中文标题】std::move 将 std::string 移动到另一个线程时出错【英文标题】:std::move gives error for moving std::string to another thread 【发布时间】:2017-01-05 11:42:28 【问题描述】:

在下面的代码中,std::move 给出了 2 个这样的错误并将我带到一个名为 functional 的文件:

    1. /usr/include/c++/4.9/functional:1665: error: no type named 'type' in 'class std::result_of<Fctor(std::basic_string<char>)>'
   typedef typename result_of<_Callable(_Args...)>::type result_type;
                                                         ^

    2. /usr/include/c++/4.9/functional:1695: error: no type named 'type' in 'class std::result_of<Fctor(std::basic_string<char>)>'
     _M_invoke(_Index_tuple<_Indices...>)
     ^

现在,将 std::move 替换为 std::ref 可以正常工作。我正在使用 C++11 支持的 QT Creator 进行编码。我正在从 here 学习 C++ 多线程,同样的代码在该视频上运行良好。

    #include <utility>
    #include <iostream>
    #include <thread>
    #include <string>

    using namespace std;

    class Fctor
    
    public:
        void operator()(std::string& msg)
        
            cout << "t1 says: " << msg << endl;
            msg = "Trust is the mother of deceit.";
            std::cout << std::this_thread::get_id() << endl;
        
    ;

    int main()
    
        string str = "Where there is no trust there is no love.";
        std::cout << std::this_thread::get_id() << endl;

        Fctor fct;
        std::thread t1( fct, std::move(str)); // DOES NOT WORK
        //std::thread t1( fct, std::ref(str) );
        std::cout << t1.get_id() << endl;

        std::thread t2=std::move(t1);

        t2.join();
        cout << "from main: " << str << endl;

        return 0;
    

【问题讨论】:

这不是您代码中的std::move,而是线程用来将参数传递给处理程序的那个(在您的情况下需要一个非 const 左值)。这个问题有很多重复。 【参考方案1】:

问题是你的仿函数 (std::string&amp; msg) ,你的函数得到一个左值引用,然后你将它作为右值引用传递。

这就是为什么使用std::ref 成功,而std::move 失败,但是如果你想从主线程中读取字符串,为什么还要尝试将它移动到线程构造函数中?

此外,您的代码呈现未定义的行为;你从t1 写给str,同时从主线程读取它。这引入了具有未定义行为的数据竞争条件。

我认为您需要确定字符串操作的确切行为。并且不要忘记将数据与锁同步。

【讨论】:

"你将它作为 r-value-reference 传递",这就是 std::thread 所做的 @David Haim 感谢您的回答和解释。我是 C++ 的初学者。 void operator()(std::string&& msg) -> 解决了。代码有效。 @muglikar 您是一般编程的初学者吗? "当您从主线程读取时从 t1 写入 str 时,您的代码呈现未定义行为"问题不是竞争条件,而是事实字符串已从移出 @DavidHaim 在某种程度上是的。

以上是关于std::move 将 std::string 移动到另一个线程时出错的主要内容,如果未能解决你的问题,请参考以下文章

移出三元运算符的一侧

从初始化列表初始化,但没有 ... ?

std::forward vs std::move 同时将左值绑定到右值引用

std::move()和std::forward()

std :: move和std :: forward之间有什么区别

什么时候用std::move()?