1

When I generate a new thread (std::thread) with a function the arguments of that function are by value - not by reference.

So if I define that function with a reference argument (int& nArg) my compiler (mingw 4.9.2) outputs an error (in compilian-suaeli something like "missing copy constructor" I guess ;-)

But if I make that reference argument const (const int& nArg) it does not complain.

Can somebody explain please?

4
  • 10
    believe it or not, some are able to read and understand what you call "compilian-suaeli", so please include the full error message in the question. Btw also some can read code, so please add a minimal reproducible example Commented Jun 22, 2017 at 9:09
  • I do not doubt it. With that term I meant that typical compiler messages that don't help much to find the cause. Commented Jun 22, 2017 at 9:31
  • You should be able to get your error output in English, e.g. by setting LC_ALL=C in the environment. Commented Jun 22, 2017 at 9:38
  • wewe ni suali? ;-) Commented Jun 22, 2017 at 9:51

2 Answers 2

1

If you want to pass reference, you have to wrap it into std::reference_wrapper thanks to std::ref. Like:

#include <functional>
#include <thread>

void my_function(int&);

int main()
{
    int my_var = 0;
    std::thread t(&my_function, std::ref(my_var));

    // ...
    t.join();
}
Sign up to request clarification or add additional context in comments.

6 Comments

Yes, thanks, I found out myself ;-) But I was wondering why it works with reference when I make the argument const.
Look at thread, "The arguments to the thread function are moved or copied by value", so there are temporary, and cannot bind to non-const reference.
No complain of the compiler if I do void my_function (const int&); int my_var = 0; std::thread t(&my_function, my_var);
Because the temporary can bind to const reference.
Looks like that is the answer. Although I don't understand so far. I will have to think that over, read information. Thank you!
|
0

std::thread's arguments are used once.

In effect, it stores them in a std::tuple<Ts...> tup. Then it does a f( std::get<Is>(std::move(tup))...).

Passing std::get an rvalue tuple means that it is free to take the state from a value or rvalue reference field in the tuple. Without the tuple being an rvalue, it instead gives a reference to it.

Unless you use reference_wrapper (ie, std::ref/std::cref), the values you pass to std::thread are stored as values in the std::tuple. Which means the function you call is passed an rvalue to the value in the std::tuple.

rvalues can bind to const& but not to &.

Now, the std::tuple above is an implementation detail, an imagined implementation of std::thread. The wording in the standard is more obtuse.


Why does the standard say this happens? In general, you should not bind a & parameter to a value which will be immediately discarded. The function thinks that it is modifying something that the caller can see; if the value will be immediately discarded, this is usually an error on the part of the caller.

const& parameters, on the other hand, do bind to values that will be immediately discarded, because we use them for efficiency purposes not just for reference purposes.

Or, roughly, because

const int& x = 7;

is legal

int& x = 7;

is not. The first is a const& to a logically discarded object (it isn't due to reference lifetime extension, but it is logically a temporary).

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.