Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.3k views
in Technique[技术] by (71.8m points)

c++ - Passing an array by reference to thread

I have an array that needs to be passed to multiple threads to be worked on. The array size is know at compile time. Here is a working reduction to the essentials where the function is called directly, not via a thread:

#include <thread>

template <class TYPE>
void function(TYPE& data, std::size_t row, std::size_t column){
    data[row-1][column-1]=2;
}

int main(){
    const int column(5),row(2);
    std::array<std::array<int, column>, row> arr;
    function(arr, row, column);
    return data[row-1][column-1];
}

The code returns 2, as expected. If I call the function via

    std::thread worker(function<std::array<std::array<int,column>,row>>, arr, row, column);

I get the following compiler error:

g++ Testo.cpp -o Testo -std=c++11 -lpthread
In file included from /usr/include/c++/4.8/thread:39:0,
                 from Testo.cpp:2:
/usr/include/c++/4.8/functional: In instantiation of ‘struct std::_Bind_simple<void (*(std::array<std::array<int, 5ul>, 4ul>, int, int))(std::array<std::array<int, 5ul>, 4ul>&, long unsigned int, long unsigned int)>’:
/usr/include/c++/4.8/thread:137:47:   required from ‘std::thread::thread(_Callable&&, _Args&& ...) [with _Callable = void (&)(std::array<std::array<int, 5ul>, 4ul>&, long unsigned int, long unsigned int); _Args = {std::array<std::array<int, 5ul>, 4ul>&, const int&, const int&}]’
Testo.cpp:13:82:   required from here
/usr/include/c++/4.8/functional:1697:61: error: no type named ‘type’ in ‘class std::result_of<void (*(std::array<std::array<int, 5ul>, 4ul>, int, int))(std::array<std::array<int, 5ul>, 4ul>&, long unsigned int, long unsigned int)>’
       typedef typename result_of<_Callable(_Args...)>::type result_type;
                                                             ^
/usr/include/c++/4.8/functional:1727:9: error: no type named ‘type’ in ‘class std::result_of<void (*(std::array<std::array<int, 5ul>, 4ul>, int, int))(std::array<std::array<int, 5ul>, 4ul>&, long unsigned int, long unsigned int)>’
         _M_invoke(_Index_tuple<_Indices...>)
         ^

I can change my template to

template <class TYPE>
void function(TYPE data, std::size_t row, std::size_t column){
    data[row-1][column-1]=2;
}

and the compiler no longer complains, but main then returns 0 as the array is no longer passed by reference. What is the appropriate first argument for the thread to call the correct template to pass the array by reference, as is working when calling the function directly?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Your function expects a reference to the array but std::thread stores decayed copies of the bound arguments. Array-to-pointer decay results in a prvalue of pointer type. To fix, pass arr through a std::reference_wrapper to preserve the type:

std::thread worker(..., std::ref(arr), row, column);

You might also want to use a lambda so you won't have to explicitly pass the template arguments:

std::thread worker([&arr]{ return function(arr, row, column); });

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...