Difference Between Pointer and Reference as Thread Parameter

Difference between pointer and reference as thread parameter

The constructor of std::thread deduces argument types and stores copies of them by value. This is needed to ensure the lifetime of the argument object is at least the same as that of the thread.

C++ template function argument type deduction mechanism deduces type T from an argument of type T&. All arguments to std::thread are copied and then passed to the thread function so that f1() and f2() always use that copy.

If you insist on using a reference, wrap the argument using boost::ref() or std::ref():

thread t1(f1, boost::ref(ret));

Or, if you prefer simplicity, pass a pointer. This is what boost::ref() or std::ref() do for you behind the scene.

C++ Objects: When should I use pointer or reference

A reference is basically a pointer with restrictions (has to be bound on creation, can't be rebound/null). If it makes sense for your code to use these restrictions, then using a reference instead of a pointer allows the compiler to warn you about accidentally violating them.

It's a lot like the const qualifier: the language could exist without it, it's just there as a bonus feature of sorts that makes it easier to develop safe code.

Multithreading - why working on a reference doesn't change it, while on a pointer works properly

1) Your code is not thread safe (concurrent push_back on a vector)

2) Arguments are passed by value by default to std::thread. This semantic of copying the arguments is natural with threads : any argument will be copied/moved to thread-accessible storage. Doing so, the std:::thread does its best to avoid concurrency access to shared objects.

Use std::ref to pass an argument by reference to your thread callable :

thread t1(doSomething, std::ref(v));
thread t2(doSomething, std::ref(v));
^^^^^^^^

Without std::ref, neither gcc or clang compile this code.


For future reference, std::thread constructors are described in section § 30.3.1.2 of the C++ standard.

When to use references vs. pointers

Use reference wherever you can, pointers wherever you must.

Avoid pointers until you can't.

The reason is that pointers make things harder to follow/read, less safe and far more dangerous manipulations than any other constructs.

So the rule of thumb is to use pointers only if there is no other choice.

For example, returning a pointer to an object is a valid option when the function can return nullptr in some cases and it is assumed it will. That said, a better option would be to use something similar to std::optional (requires C++17; before that, there's boost::optional).

Another example is to use pointers to raw memory for specific memory manipulations. That should be hidden and localized in very narrow parts of the code, to help limit the dangerous parts of the whole code base.

In your example, there is no point in using a pointer as argument because:

  1. if you provide nullptr as the argument, you're going in undefined-behaviour-land;
  2. the reference attribute version doesn't allow (without easy to spot tricks) the problem with 1.
  3. the reference attribute version is simpler to understand for the user: you have to provide a valid object, not something that could be null.

If the behaviour of the function would have to work with or without a given object, then using a pointer as attribute suggests that you can pass nullptr as the argument and it is fine for the function. That's kind of a contract between the user and the implementation.

What's the difference between ( this ) and ( std::ref(*this) )

In the context of launching a thread running a member function of a class A, those calls are equivalent.

The first is like

void compiler_created_on_new_thread(A * a) { a->Func(); }

The second is like

void compiler_created_on_new_thread(A & a) { a.Func(); }

If instead A were a namespace, they would be distinguishable

namespace A {
void Func(Thing *) { std::cout << "pointer"; }
void Func(Thing &) { std::cout << "reference"; }
}

The first would display "pointer" and the second "reference"

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


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.

Why does passing object reference arguments to thread function fails to compile?

Threads copy their arguments (think about it, that's The Right Thing). If you want a reference explicitly, you have to wrap it with std::ref (or std::cref for constant references):

std::thread t(foo, std::ref(std::cout));

(The reference wrapper is a wrapper with value semantics around a reference. That is, you can copy the wrapper, and all copies will contain the same reference.)

As usual, this code is only correct as long as the object to which you refer remains alive. Caveat emptor.

Difference between pointer-to-pointer vs reference-to-pointer (C++)

The first example is that of a reference to a pointer, ie. a reference to a type IEnumWbemClassObject*:

HRESULT Query ( IN BSTR sQuery, OUT IEnumWbemClassObject* &pEnumerator );

Therefore if pEnumerator is declared as a IEnumWbemClassObject* (which I'm assuming it is), you don't need to explicitly pass the address of pEnumerator to the function or dereference the variable inside the function in order to change where pEnumerator points (which would otherwise be required with an argument of IEnumWbemClassObject**).

A reference to a pointer has the same behaviour as a reference to any other type, just think of the above example as being a "reference to a pointer" and not a "pointer to a reference." There's no such thing as a pointer to a reference.



Related Topics



Leave a reply



Submit