9

When creating a thread that calls a member function, is there a difference between passing a pointer to the current class or passing a reference?

From the example below, does method1 behave the same as method2? Are there any differences?

class MyClass
{
public:
    MyClass(){};
    ~MyClass(){};
    void memberFunction1()
    {
        //method 1
        std::thread theThread(&MyClass::memberFunction2, this, argumentToMemberFunction2)

        //method 2
        std::thread theThread(&MyClass::memberFunction2, std::ref(*this), argumentToMemberFunction2)
    }
    void memberFunction2(const double& someDouble){};
}
user3731622
  • 4,844
  • 8
  • 45
  • 84
  • 2
    Assuming it compiles, there shouldn't be. References are syntactic sugar for pointers. Doesn't mean it couldn't screw up the compiler though, as it's syntactically dubious to pass the `std::ref` `reference_wrapper` when the call is performed (internally) with `this` as a pointer as the first object. – ShadowRanger Dec 17 '15 at 23:03

1 Answers1

4

No, there are no differences, but note that using a reference wrapper has only become possible with the acceptance of LWG 2219 as a defect report at the Oct 2015 WG21 meeting.*

Using std::ref may help in cases where you have a named object instance rather than this, since this is quite easy to spell. But consider the following situation, in which you'd like to stay nicely const-correct:

A a;
std::thread(&A::foo, std::cref(a), 1, 2);

This may be easier to read than:

std::thread(&A::foo, &(const_cast<const A&>(a)), 1, 2);
std::thread(&A::foo, &as_const(a), 1, 2);
std::thread(&A::foo, const_cast<const A*>(&a), 1, 2);

*) Vendors that keep distinct language dialects around, like GCC's and Clang with the -std flag), will typically consider defects to apply to all dialects and "fix" the implementations. Defects are things that "were always meant to be the way we say now".

Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
  • The `std::ref` example shouldn't even compile, *INVOKE* doesn't have special handling for `reference_wrapper` - https://cplusplus.github.io/LWG/lwg-defects.html#2219 – Praetorian Dec 17 '15 at 23:22
  • Glad you undeleted :) Looks like this was added very recently to libstdc++ - https://gcc.gnu.org/bugzilla/show_bug.cgi?id=59768 – Praetorian Dec 17 '15 at 23:31
  • It is indeed in the working draft now, just looked at N4567 and its definition of *INVOKE* includes handling `reference_wrapper` – Praetorian Dec 17 '15 at 23:42
  • @Praetorian: Forget it, it does apply. I was just confused. Yes, the LWG issue changes the interpretation from `(*t1).*f` to `t1.get().*f` when `t1` is a reference wrapper, which finally makes this work. This has been accepted as a defect report, so I suppose implementers will patch this even into previous language dialects (like GCC's `c++11` and `c++14`). – Kerrek SB Dec 17 '15 at 23:44
  • @Praetorian: Looks like someone needs to update the documentation for [`std::invoke`](http://en.cppreference.com/w/cpp/utility/functional/invoke). – Kerrek SB Dec 17 '15 at 23:54
  • Maybe TC or Cubbi will come across this answer and do it :) The "possible implementation" needs some unwrapping code added to it also. – Praetorian Dec 18 '15 at 00:05