传递对线程的引用时真的需要 std::ref 吗?

Llo*_*ley 2 c++ multithreading c++11 stdthread

我正在阅读 C++ Concurrency in Action 和第 2 章,我相信即使是函数原型,例如:

void MagicFunc(Data& myData);
Run Code Online (Sandbox Code Playgroud)

旨在如下使用:

Data dataExample;
thread t(MagicFunc,dataExample);
Run Code Online (Sandbox Code Playgroud)

我真的应该这样做

Data dataExample
thread t(MagicFunc,std::ref(dataExample));
Run Code Online (Sandbox Code Playgroud)

否则我期望发生在“dataExample”上的更改将不会发生。具体来说,它声明如下:

尽管 MagicFunc 期望通过引用传递第二个参数,但 std::thread 构造函数 t 不知道;它无视函数预期的参数类型,并盲目地复制提供的值。当它调用 Magicfunc 时,它最终会传递对数据内部副本的引用,而不是对数据本身的引用。因此,当线程完成时,这些更新将被丢弃,因为所提供参数的内部副本被销毁,并且 process_widget_data 将传递一个未更改的 Data myData 而不是正确更新的版本。

但是,使用以下程序对此进行测试

#include <iostream>
#include <thread>
#include <vector>
#include <chrono>
#include <assert.h>
using namespace std;
using namespace std::chrono;

const int NUM_VALS = 50000000;

#define _MULTICORE 

void AddValuesToSlots(vector<int>& vecVals,vector<int>::iterator& begin,
                      int num,int startNum){
    int i = startNum;
    auto end = begin + num;
    for (auto itr = begin; itr < end; ++itr){
        *itr = i++;
    }
}

int main()
{
    vector<int> vecVals;
    vecVals.resize(NUM_VALS);

    //get number of cores and divide up the workload
    unsigned int numCores = thread::hardware_concurrency();
    unsigned int slotsPerThread = NUM_VALS / numCores;

    //for timing
    high_resolution_clock::time_point t1 = high_resolution_clock::now();


    thread* t = new thread[numCores];

    //get the iterator to the beginning
    auto begin = vecVals.begin();

#ifdef _MULTICORE
    for (int core = 0; core < numCores; ++core){
        t[core] = thread(AddValuesToSlots, vecVals, begin + core*slotsPerThread,
            slotsPerThread, core*slotsPerThread);
    }

    for (int core = 0; core < numCores; ++core){
        t[core].join();
    }
#else
    AddValuesToSlots(vecVals, begin, NUM_VALS, 0);
#endif


    delete[] t;

    //how long did it take?
    high_resolution_clock::time_point t2 = high_resolution_clock::now();
    cout << duration_cast<milliseconds>(t2-t1).count() << endl;

#ifdef _DEBUG
    //test that the values are correct
    for (int slot = 0; slot < NUM_VALS; ++slot)
        assert(vecVals[slot] == slot);
#endif

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

我试过vecVals用 astd::ref和 without封装,两次都没有问题。是std::ref那么真的有必要和提供错误的信息?

谢谢

Sev*_*eux 5

你没有直接改变 vecVals 。迭代器正在工作,因为复制迭代器是可以的,它仍然指向相同的内存地址