Search code examples
c++c++11pass-by-referencestdthread

Why are we not allowed to pass pure reference arguments to std::thread but are allowed to pass raw pointers?


Lets say I want to pass some reference argument to the thread - the standard only allows this by using std::ref.

Now lets consider this code that has undefined behaviour (see comments)

    void thread_fun(int& x) {
        std::this_thread::sleep_for(std::chrono::seconds(1));
        x = -2;
    }

    int main() {
        {
            int a = 10;
            std::thread t(thread_fun, std::ref(a));
            std::cout << "in main: " << a << '\n';
            t.detach();
        }
        // here thread t may still running and writing to an object "a" which
        // already destroyed is undefined behaviour
        return 0;
    }

Without using std::ref(a) it does not compile - is this some kind protection from undefined behaviour at compile time ?

If it is, then the big question for me is why are we allowed to pass raw pointers to std::thread ?

For example, I can rewrite the same code above to pass a pointer like so:

    void thread_fun(int* x) {
        std::this_thread::sleep_for(std::chrono::seconds(1));
        *x = -2;
    }
    //...
    {
        int a = 10;
        std::thread t(thread_fun, &a);
        //...
    }

And this also contains undefined behaviour, but no compile time protection here !?

What is special in case of passing references ??


Solution

  • What is special in case of passing references ??

    The special thing is that passing by reference looks identical at the call site to passing by value.

    Every other case you show leaves at least a hint at the call site that you may be doing something risky, without having to read the function prototype.