In C, a->b
is precisely equivalent to (*a).b
. The "arrow" notation was introduced as a convenience; accessing a member of a struct via a pointer was fairly common and the arrow notation is easier to write/type, and generally considered more readable as well.
C++ adds another wrinkle as well though: operator->
can be overloaded for a struct
/class
. Although fairly unusual otherwise, doing so is common (nearly required) for smart pointer classes.
That's not really unusual in itself: C++ allows the vast majority of operators to be overloaded (although some almost never should be, such as operator&&
, operator||
and operator,
).
What is unusual is how an overloaded operator->
is interpreted. First, although a->b
looks like ->
is a binary operator, when you overload it in C++, it's treated as a unary operator, so the correct signature is T::operator()
, not T::operator(U)
or something on that order.
The result is interpreted somewhat unusually as well. Assuming foo
is an object of some type that overloads operator->
, foo->bar
is interpreted as meaning (f.operator->())->bar
. That, in turn, restricts the return type of an overloaded operator->
. Specifically, it must return either an instance of another class that also overloads operator->
(or a reference to such an object) or else it must return a pointer.
In the former case, a simple-looking foo->bar
could actually mean "chasing" through an entire (arbitrarily long) chain of instances of objects, each of which overloads operator->
, until one is finally reached that can refer to a member named bar
. For an (admittedly extreme) example, consider this:
#include <iostream>
class int_proxy {
int val;
public:
int_proxy(): val(0) {}
int_proxy &operator=(int n) {
std::cout<<"int_proxy::operator= called\n";
val=n;
return *this;
}
};
struct fubar {
int_proxy bar;
} instance;
struct h {
fubar *operator->() {
std::cout<<"used h::operator->\n";
return &instance;
}
};
struct g {
h operator->() {
std::cout<<"used g::operator->\n";
return h();
}
};
struct f {
g operator->() {
std::cout<<"Used f::operator->\n";
return g();
}
};
int main() {
f foo;
foo->bar=1;
}
Even though foo->bar=1;
looks like a simple assignment to a member via a pointer, this program actually produces the following output:
Used f::operator->
used g::operator->
used h::operator->
int_proxy::operator= called
Clearly, in this case
foo->bar
is
not (even close to) equivalent to a simple
(*foo).bar
. As is obvious from the output, the compiler generates "hidden" code to walk through the whole series of overloaded
->
operators in various classes to get from
foo
to (a pointer to) something that has a member named
bar
(which in this case is also a type that overloads
operator=
, so we can see output from the assignment as well).
{http://stackoverflow.com/questions/13023320/the-arrow-member-operator-in-c}
Pointers Vs Reference. When to use and why?
Note:- Not covering the definitions
1) References can never be null.
string& str1; // Error! References must be initialized string str("xyzzy");
string& str1 = str; // okay, str1 refers to str
There is no such restriction in pointer. SO whenever we use pointer we tend to check for the possibility of its being null and then we use it. We dont have to bother about this when using references. This way references are safer to use.
2) Pointer may be reassigned to point out to some other objects as well. this is not the case with reference, it is assigned to the object with which it is initialized.
Hence, use pointers when there is possibility of the pointer referring to different things.
Use reference when you wanted to refer to only one object.
Note:- When ever you are implementing certain operators always use references.