下面是引用自 C++ Concurrency in Action $2.2
的例子void f(int i,std::string const& s);
void oops(int some_param)
{
char buffer[1024];
sprintf(buffer, "%i",some_param);
std::thread t(f,3,buffer);
t.detach();
}
作者说这是未定义的行为:
In this case, it’s the pointer to the local variable
buffer
that’s passed through to the new thread, and there’s a significant chance that the function oops will exit before the buffer has been converted to astd::string
on the new thread, thus leading to undefined behavior. The solution is to cast tostd::string
before passing the buffer to the std::thread constructor:
void f(int i,std::string const& s);
void not_oops(int some_param)
{
char buffer[1024];
sprintf(buffer,"%i",some_param);
std::thread t(f,3,std::string(buffer));
t.detach();
}
但我对此感到困惑。因为就我而言,这两种形式之间没有区别:
在第一个代码片段中,当将buffer
作为参数传递给函数时,它还会生成一个临时的std::string
对象,并将函数参数绑定(bind)到该对象上临时对象。所以它与第二个代码片段完全相同。唯一的区别是前一个中的临时对象是由编译器隐式生成的,而后一个是由用户显式生成的。
最佳答案
这里有两个步骤:
- 无论您传递给
std::thread
的构造函数,该构造函数都会将其衰减复制到新线程可访问的存储中。 - 然后新线程使用那些复制的参数调用可调用对象。
第一个片段复制了一个指向缓冲区的指针。调用新线程的可调用对象然后将该指针转换为 std::string
,但到那时缓冲区可能已经消失。
第二个片段在保证有效时在原始线程中执行转换。临时 std::string
然后由 std::thread
构造函数移动到中间存储中。
关于c++ - 为什么不将临时对象传递给另一个线程会导致未定义的行为?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50036132/