2

Possible Duplicate:
Why does C have a distinction between -> and . ?

What is the real reason for a programmer to have to differentiate between . and -> when accessing a member of an object?

void foo( Point &p ) {
    p.x ;
    p->y; // syntax error
} 

void foo( Point *p ) {
    p.x ; // syntax error
    p->y;
} 

I mean, one way or another, they both refer to an object, p.

  • Why do I have to bother checking every time what p is ? Can't the compiler understand ?

  • Why haven't they allowed it to accept . syntax for both? That would be fine for stack objects too.

And if it is due to C-tradition,

  • Why don't they allow both . and -> accessors?

For more than 15 years, I have always humbly considered the compiler errors as being my fault !

Community
  • 1
  • 1
Grim Fandango
  • 2,296
  • 1
  • 19
  • 27
  • Possible duplicate of http://stackoverflow.com/questions/1813865/why-does-c-have-a-distinction-between-and/1813883#1813883 . Although this concerns C, many of the answers concern C++ issues. – CB Bailey Oct 05 '10 at 15:33
  • It is what it is. Get used to it or use a different language. Unless Kernighan or Ritchie have started posting on StackOverflow, you're unlikely to get a good answer. – Mark Ransom Oct 05 '10 at 15:35
  • 3
    I see your point, but I think the idea of "compiler errors being my fault" misses the point somewhat. *Errors in and of themselves are a good thing,* which is obvious when you compare errors with silent failure to compile. It is not the error messages, but the failure to accept and compile this code that is annoying. Right? Small point, but I hope it clarifies the question: why does the compiler (equivalent to: the C++ language spec) not allow this expression? Which is what you said in your bullet points. – LarsH Oct 05 '10 at 15:37

9 Answers9

8

Because p->d actually means (*p).d. It does a dereference and then a member access. References behave like objects thus they don't need dereferencing (they are also a C++ feature, while pointer are inherited from C); it has been kept that way for backwards compatibility.

C++ is full of inconsistencies like this, but there's usually no better choice to add new features and keep old code working. Rewriting the old code is not an option.

CMircea
  • 3,543
  • 2
  • 36
  • 58
  • Now imageine d is next an a linked list. `(*(*(*(*p).next).next).next).next` is the same as `p->next->next->next->next` – Martin York Oct 05 '10 at 16:10
6

Because you might have a smart pointer. In that case, you can access the smart pointer's members using . and the real object's members using ->.

Khaled Alshaya
  • 94,250
  • 39
  • 176
  • 234
  • 8
    Isn't it the other way around - smart pointers taking advantage of this feature rather than the feature being there so that smart pointers can exist... – naumcho Oct 05 '10 at 15:40
  • 2
    It could be both. C obviously distinguished between `.` and `->` before there were such things as smart pointers. But C++ *could* in principle have chosen to merge them as the OP suggested, allowing you to use either syntax. But then it'd be impossible to implement smart pointers – jalf Oct 05 '10 at 15:51
  • @user779 I would say you have a point :) – Khaled Alshaya Oct 05 '10 at 15:55
4

They are not the same.

. is when you have an actual object.
-> is when you have a pointer to an object.

The . operator cannot be overloaded, while the -> operator can be overloaded.

abelenky
  • 63,815
  • 23
  • 109
  • 159
  • The OP's question isn't when to use what, but why the two different syntax forms exist in the first place. – jalf Oct 05 '10 at 15:52
3

In theory, at least in C, the language could have been designed to do this. D (for one example) does exactly what you're asking about.

In C++, things could be a big uglier -- it's entirely possible for x->y and x.y to both be valid, but mean entirely different things (i.e., a smart pointer that overloads operator->):

#include <iostream>

class P { 
    class inner { 
    public:
        inner() : x(1) {}
        int x;
    } i;
public:
    int x;


    P() :x(0) {}

    inner *operator->() { return &i; }
};

int main() { 
    P p;
    std::cout << p.x << "\t" << p->x << "\n";
    return 0;
}
Jerry Coffin
  • 476,176
  • 80
  • 629
  • 1,111
  • The use of separate delimiters in C is a *good design feature*, which is unfortunately missing in C#. In C, in `foo = bar; foo->boz = 3;` the second statement does not modify `foo` but does modifiy `bar->boz`. By contrast, in `foo = bar; foo.boz = 3;`, the second statement does modify `foo` but does not modify `bar.boz`. I wish C# and .NET had allowed non-field members to be declared as using one or other operator, with `->` implying that `this` would be passed by value and `.` implying pass by ref. Class fields would use `->` and struct fields would be `.`. – supercat Sep 19 '13 at 17:07
3

Smart pointers: they might have both members and point to some other values. For example:

boost::smart_ptr<someclass> x(new someclass())
x->some_method();
x.reset();
liori
  • 40,917
  • 13
  • 78
  • 105
2

Because pointers and references are different, and are treated differently ?

I appreciate the visual difference when I'm reading code.

luke
  • 36,103
  • 8
  • 58
  • 81
2

Consider the following piece of code:

x.myInt = 3;
cout << (int)&x <<< endl;

What are we printing here? The address of a pointer or the address of the object? I welcome the difference between . and -> because it gives you more context on the code.

With your suggested change we wouldn't know the difference without looking up what type x is.

Brian R. Bondy
  • 339,232
  • 124
  • 596
  • 636
2

It's a matter of convenience: p->foo is the same as (*p).foo

It's like asking why have a ++ or a += operator when you can express the same logic with simple + and = operators.

naumcho
  • 18,671
  • 14
  • 48
  • 59
  • Now imageine foo is next an a linked list. (*(*(*(*p).next).next).next).next is the same as p->next->next->next->next – Martin York Oct 05 '10 at 16:11
0

I can think of one reason: the more complex the mapping between what the developer wrote and what they actually wanted to happen, the more difficult it is to figure out what they really meant when there is a type or syntax error.

LarsH
  • 27,481
  • 8
  • 94
  • 152