問題描述
示例如下:
#include<iostream>
#include<thread>
using namespace std;
void f1(double& ret) {
ret=5.;
}
void f2(double* ret) {
*ret=5.;
}
int main() {
double ret=0.;
thread t1(f1, ret);
t1.join();
cout << "ret=" << ret << endl;
thread t2(f2, &ret);
t2.join();
cout << "ret=" << ret << endl;
}
輸出是:
ret=0
ret=5
使用 gcc 4.5.2 編譯,帶有和不帶有 -O2
標志.
Compiled with gcc 4.5.2, with and without -O2
flag.
這是預期的行為嗎?
這個程序是免費的數據競爭嗎?
Is this program data race free?
謝謝
推薦答案
std::thread
的構造函數推導參數類型并按值存儲它們的副本.這需要確保參數對象的生命周期至少與線程的生命周期相同.
The constructor of std::thread
deduces argument types and stores copies of them by value. This is needed to ensure the lifetime of the argument object is at least the same as that of the thread.
C++ 模板函數參數類型推導機制從 T&
類型的參數推導類型 T
.std::thread
的所有參數都被復制,然后傳遞給線程函數,以便 f1()
和 f2()
始終使用該副本.
C++ template function argument type deduction mechanism deduces type T
from an argument of type T&
. All arguments to std::thread
are copied and then passed to the thread function so that f1()
and f2()
always use that copy.
如果您堅持使用引用,請使用 boost::ref()
或 std::ref()
包裝參數:
If you insist on using a reference, wrap the argument using boost::ref()
or std::ref()
:
thread t1(f1, boost::ref(ret));
或者,如果您更喜歡簡單,請傳遞一個指針.這就是 boost::ref()
或 std::ref()
在幕后為您做的事情.
Or, if you prefer simplicity, pass a pointer. This is what boost::ref()
or std::ref()
do for you behind the scene.
這篇關于指針和引用作為線程參數的區別的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!