我有以下代码块,我期望lambda捕获列表中的i
按值传递,并且i
输出应该是不同的。
然而,实际结果是输出20行19 is completed
。
我尝试将此行std::thread t([&func](){
更改为std::thread t([func](){
,输出可能会打印不同的i
值。
我的问题是为什么std::thread t([&func](){
和std::thread t([func](){
将导致i的不同输出值?
void DoSomething(std::function<void()> func)
{
std::thread t([&func](){
//do something
sleep(1);
if (func)
func();
});
t.detach();
}
int main(int argc, const char * argv[]) {
std::mutex mtx;
for (int i = 1 ; i < 20; i ++) {
DoSomething([i, &mtx](){
std::unique_lock<std::mutex> lock(mtx);
std::cout << i << " is completed" << std::endl;;
});
}
sleep(10);
}
答案 0 :(得分:2)
您正在捕获对DoSomething
参数func
的引用。
当你的线程执行时,该参数的生命周期已经结束,所以你有一个悬空引用并且使用它是未定义的。
答案 1 :(得分:0)
t
中的线程对象DoSomething()
接收对func
对象的引用,该引用按值传递。执行func()
时,可能正在等待调用mutex
的{{1}}。同时将调用std::unique_lock<std::mutex> lock(mtx);
并通过销毁by值退出该函数参数t.detach()
。如@molbidnilo所说,这将导致悬空参考。
问题可以通过调用func
而不是t.join();
来解决。
答案 2 :(得分:0)
如果使用t.detach(),则线程独立运行,现在你通过引用传递函数对象,所以如果在独立线程试图引用时销毁了函数对象,那么这不会导致崩溃该程序。 但是如果按值传递函数对象,则会解决此问题。我在我的机器上测试了你的代码,它在通过引用使用传递的函数对象时崩溃了。