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& 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 同时将左值绑定到右值引用