Search code examples
c++multithreadingpass-by-referencestdthreadpass-by-const-reference

Reference at std::thread parameters


I have two functions

void f(const int &x) {}
void g(int& x) {}

I can make

int x = 0;
std::thread t1(f, x);

But I can't create std::thread t2(g, x), in this case i need make std::ref(x) instead of just x, why is it necessary?

And why it possible to create t1 without std::cref?


Solution

  • Your f() function does not work as you expect without std::cref().

    Although f() does not intent to change the value behind x, it does not mean that the value behind this reference cannot be mutated elsewhere.

    In this example, without std::cref() a copy of the original int is put in the thread stack, and x references this copy; we see 1 and 1.

    On the other hand, with std::cref(), x still references the original; we see 1 and 2.

    /**
      g++ -std=c++17 -o prog_cpp prog_cpp.cpp \
          -pedantic -Wall -Wextra -Wconversion -Wno-sign-conversion \
          -g -O0 -UNDEBUG -fsanitize=address,undefined -pthread
    **/
    
    #include <iostream>
    #include <thread>
    
    using namespace std::chrono_literals;
    void
    f(const int &x)
    {
      std::cout << "x=" << x << '\n';
      std::this_thread::sleep_for(1000ms);
      std::cout << "x=" << x << '\n';
    }
    
    int
    main()
    {
      int i=1;
      // std::thread th{f, i}; // copy to thread stack
      std::thread th{f, std::cref(i)}; // reference the original i
      std::this_thread::sleep_for(500ms);
      i+=1;
      th.join();
      return 0;
    }