Reputation: 10490
The following both call the function T::f
on object t
.
1. t.f();
2. t.T::f();
3. (t.*&T::f)();
I've seen the second one used where the other was not. What is the difference between these two and in what situation should one be preferred?
Thanks.
EDIT: Sorry, I forgot about the second one t.T::f()
. I added that one in.
Upvotes: 1
Views: 111
Reputation: 154045
The call t.f()
and (t.*&T::f)()
are semantically identical and are the "normal" way to call a member functions. The call t.T::f()
calls T::f()
even if f()
is an overridden virtual function.
The expression (t.*&T::f)()
calls a member function by obtaining a pointer to a member function. The only potential effect that this expression could have is that it might inhibit inlining the function for some compilers. Using a variable obtained from &T::f
to call a member function would be a customization point but directly calling the function is merely obfuscation and potentially a pessimization (if the compiler isn't capable to do sufficient const propagation to detect that the address can't change).
What I could imagine is that someone tried to inhibit a virtual function call on t
. Of course, this doesn't work this way because the pointer to member will still call the correct virtual function. To inhibit virtual dispatch you'd use t.T::f()
.
You should prefer t.f()
over (t.*&T::f)()
. If you want to inhibit virtual dispatch you'd use t.T::f()
otherwise you'd use t.f()
. The primary use for inhibiting virtual dispatch is to call the base class version of a function from within an overriding function. Otherwise it is rarely useful.
Upvotes: 4
Reputation: 81409
The first one is the regular one, that's the one you should prefer. The second one takes a member function pointer to f
, dereferences it for t
, and then calls it.
If there is an actual benefit in that extra trip I am not aware of it. This is the member version of *&f()
when calling a free function.
The one that you added later on, t.T::f()
, is statically dispatched so that the f
of T
is called even if it were virtual and t
were a derived class of T
with its own implementation. It effectively inhibits the virtual call mechanism.
Upvotes: 1
Reputation: 6678
The second one is pointless, it's just obfuscated code. No it doesn't disable virtual dispatch nor inlining. They both do the exact same thing, in each and every case.
Upvotes: -1