views:

406

answers:

3

Is there any difference in performance - or otherwise - between:

ptr->a();

and

(*ptr).a(); 

?

+16  A: 

[Edit]

If the variable is defined as T* (where T is some type) then both -> and * are the same (unless ptr is null).

If the variable is an instance of a class (by value or by reference) then -> and * should behave the same (per best practice) but this requires the class to overload them the same way.

Itay
-> and * don't operate on the type themselves T, but on a type of T*, which is a pointer.
Brian R. Bondy
If the underlying class *does* overload `->` or `*` it should overload both so that it is still the same. Otherwise it is badly designed.
Tadeusz Kopec
@Brian `->` and `*` operate on anything that defines `operator->` and `operator*`. *And* also on all pointer types.
Tadeusz Kopec
I know that the results are the same; can anyone confirm that performance - speed, efficiency - is the same?
Rachel
@Tadeusz Kopec: Read the answer by Jeremy Bell: `operator->` has special behavior that makes `x->y` inconsistent with `(*x).y` in some cases, and the behavior cannot be simulated with `operator*`
David Rodríguez - dribeas
Rachel: I know people have heard this over and over again but: Why? Who cares? Use the readable one, performance is a *second concern*. Your first concern is writing your application in an easy to manage way. Only when you find performance lacking should you even care about performance. That said, you have to *profile*: time the code and see which is faster. However in this case, they are the same thing. There should be no difference. You are new-ish to programming in C++, I'm guessing, so worry about C++, not speed.
GMan
@Tadeusz: You can overload -> But it will apply to the class not the pointers of the class. For example Cat c; c->f(), it will not apply to Cat *p = p->f(); I'm not sure why this is so highly voted up because it is wrong.
Brian R. Bondy
@Brian: I agree with you, but the original question does specify whether that variable is defined as T* or T. So, the answer is general and captures all cases
Itay
@Brian: so it should be clarified - if applied to pointers `(*).` and `->` are perfectly the same, no matter what pointee type is. If applied to object of some class, it calls appropriate operator overloads if defined or does not compile if no such overload exists. Implementations of `operator*` and `operator->` may vary, but general guideline is 'do like primitives do' so making `*` and `->` do different things I consider bad design.
Tadeusz Kopec
@Itay, @Tadeusz: Agree, the user didn't specify explicitly but I think he meant a pointer type. I agree with both of your final statements though.
Brian R. Bondy
@GMan - Simple: I do not believe in doing things without understanding why you're doing them.
Rachel
@Rachel: You didn't ask why, you asked which is more efficient. If your "Why" is "it's the most efficient", fine, but I warn against that. Micro-optimizations lose to good programming.
GMan
@GMan: Change that to "what you're doing." If there are two ways to do something, there's usually a difference. Otherwise we'd only need one way to do it. In this case I was guessing that perhaps the difference would be optimization. This was an attempt to understand the entire picture, rather than an "it works so just use it."
Rachel
@Rachel: Your question above was misleading, then. Asking which is more efficient has nothing to do with understanding why they are the same.
GMan
"(unless ptr is null)" -> do you mean "(unless ptr is null, because then both are undefined behavior)" (which is actually the case) or do you mean "(unless ptr is null, because then one behaves different)"? If the latter, then which one do you think behaves different?
Johannes Schaub - litb
+4  A: 

The -> operator is special in that in most cases it "drills-down" recursively until the result of the expression is no longer something that has an overloaded -> operator defined for it. The (*subxpression).x expression only does one dereference on subexpression, so if the result of (*subexpression) is another pointer, then this wouldn't compile (you would need to write (*(*subexpression)).x. See the following code for a better illustration:

#include <iostream>
using namespace std;

class MyClass
{
public:
    MyClass() : x(0) {}
    int x;
};

class MyPtr
{
private:
    MyClass* mObj;
public:
    MyPtr(MyClass* obj) : mObj(obj) {}
    MyClass* operator->() 
    {
        return mObj;
    }
};

int main() 
{
    MyClass obj;
    MyClass* objCPtr = &obj;
    MyClass** objCHandle = &objCPtr;
    MyPtr ptr(&obj);
    cout << ptr->x << endl;
    cout << (*(*objCHandle)).x << endl;
}

Note however, that this would not compile:

cout << objCHandle->x << endl;

Because the drill down behavior of -> only occurs when the left hand side of the expression is a class, struct, union, or generic type. In this case, objCHandle is a MyClass**, so it doesn't qualify.

Jeremy Bell
@Jeremy: I added a number of backticks, to stop the asterisks from being interpreted as formatting commands :).
Andrew Aylett
@Andrew: thanks!
Jeremy Bell
+9  A: 

Since you are asking for it in the comments. What you are probably looking for can be found in the Standard (5.2.5 Class member access):

3 If E1 has the type “pointer to class X,” then the expression E1->E2 is converted to the equivalent form (*(E1)).E2;

The compiler will produce the exact same instructions and it will be just as efficient. Your machine will not know if you wrote "->" or "*.".

Lucas
Yep. That's what I was looking for - whether or not they are the same underneath.
Rachel