0

I am not very familiar with c++11 library thread and I have two questions about the following demos. In this demo, I want to use the change value function to modify the public member variable data.

  1. The first question is that I got compiling error as the following.
  2. The second is that I want to know the principle of C++ to deal with such case. What I confused is that whether or not each thread will create a local copy for the data variable and then access it.
class TestThread
{
private:
    int *data;

    void changeValue(unsigned int index)
    {
        if (index >= 10000)
            return;

        data[index] = 1;
    }
public:
    TestThread()
    {
        data = new int[10000];
    }
    void createThread()
    {
        const int numThread = 2;
        std::vector < std::thread > threadsPool;
        for (unsigned int i = 0; i < numThread; ++i)
        {
            threadsPool.emplace_back(&TestThread::changeValue, i);
        }

        for (unsigned int i = 0; i < numThread; ++i)
        {
            threadsPool[i].join();
        }

    }
    void outputResult()
    {
        std::cout << "data valuve " << std::endl;
        std::cout << data[0] << std::endl;
        std::cout << data[1] << std::endl;
    }
    TestThread(const TestThread& t) {
   std::cout << "Calling constructor" << std::endl;
 }
    ~TestThread()
    {
        delete[] data;
    }
};


int main() {
  TestThread testclass;
  testclass.outputResult();
  testclass.createThread();
  testclass.outputResult();
  return 0;
}

The compiling error is as the following

testThread.cpp:21:58:   required from here
/usr/include/c++/7/thread:240:2: error: no matching function for call to ‘std::thread::_Invoker<std::tuple<void (TestThread::*)(long unsigned int), unsigned int> >::_M_invoke(std::thread::_Invoker<std::tuple<void (TestThread::*)(long unsigned int), unsigned int> >::_Indices)’
  operator()()
  ^~~~~~~~
/usr/include/c++/7/thread:231:4: note: candidate: template<long unsigned int ..._Ind> decltype (std::__invoke((_S_declval<_Ind>)()...)) std::thread::_Invoker<_Tuple>::_M_invoke(std::_Index_tuple<_Ind ...>) [with long unsigned int ..._Ind = {_Ind ...}; _Tuple = std::tuple<void (TestThread::*)(long unsigned int), unsigned int>]
    _M_invoke(_Index_tuple<_Ind...>)


testThread.cpp:21:58:   required from here
/usr/include/c++/7/bits/invoke.h:89:5: error: no type named ‘type’ in ‘struct std::__invoke_result<void (TestThread::*)(unsigned int), unsigned int>’
Sean
  • 691
  • 1
  • 5
  • 20
  • 1
    Looks like you could be missing the instance variable. Give `threadsPool.emplace_back(&TestThread::changeValue, this, i);` a try. – user4581301 May 16 '20 at 05:38
  • @user4581301 By passing this, Will I create a local copy of the object? – Sean May 16 '20 at 05:45
  • No. This approach would just pass in the `this` pointer for the current object. This may or may not be what you need. If I was sure, I would have written an answer. You do NOT want to copy this object, though. It doesn't observe [the Rule of Three](https://en.cppreference.com/w/cpp/language/rule_of_three), so copying it would be fatal. – user4581301 May 16 '20 at 06:01
  • I think I mis-interpreted your comment. Each `TestThread` has its own `data` and the constructor allocates storage for `data` to reference. However, because there is no support for the Rule of Three (link above), if you copy-construct a new `TestThread` its `data` will point at the same storage as the source `TestThread`'s `data`. Both will attempt to delete this allocation and [badness](https://stackoverflow.com/questions/9169774/what-happens-in-a-double-delete) will result. – user4581301 May 16 '20 at 06:19
  • @user4581301 Thank you first. The program can compile normally. Yes, this is what I mean. If I provide the copy constructor for deep copy, each thread I created is going to have its own local copy of data. If I create 10 threads, then they will use 10 * sizof(data) memory. Is that right? – Sean May 16 '20 at 06:23
  • Yes-ish. 10 copies will be 10 `data`s each with its own dynamic array of 10000 `int`s. The "-ish" is because `sizeof(data)` will return only the side of the pointer and will not include the 10000 `int`s. That has to be counted separately. – user4581301 May 16 '20 at 06:29
  • @user4581301 I add the trivial copy constructor in my class and I run the same program. It seems that we do not call it. – Sean May 16 '20 at 06:37

0 Answers0