I understand the normal operator overloading. Compiler can translate them to method call directly. I am not very clear about the -> operator. I was writing my first custom iterator and I felt like the need of -> operator. I took a look at the stl source code and implemented my own like it:
MyClass* MyClassIterator::operator->() const { //m_iterator is a map<int, MyClass>::iterator in my code. return &(m_iterator->second); }
Then I can use an instance of MyClassIterator like:
myClassIterator->APublicMethodInMyClass().
Looks like the compiler does two steps here. 1. Call the ->() method the get a temporary MyClass* variable. 2. Call the APublicMethodInMyClass on the temp variable use its -> operator.
Is my understanding correct?
The operator-> has special semantics in the language in that, when overloaded, it reapplies itself to the result. While the rest of the operators are applied only once, operator-> will be applied by the compiler as many times as needed to get to a raw pointer and once more to access the memory referred by that pointer.
The class member access operator (->) can be overloaded but it is bit trickier. It is defined to give a class type a "pointer-like" behavior. The operator -> must be a member function.
The -> is called the arrow operator. It is formed by using the minus sign followed by a greater than sign. Simply saying: To access members of a structure, use the dot operator. To access members of a structure through a pointer, use the arrow operator.
An Arrow operator in C/C++ allows to access elements in Structures and Unions. It is used with a pointer variable pointing to a structure or union. The arrow operator is formed by using a minus sign, followed by the greater than symbol as shown below. Syntax: (pointer_name)->(variable_name)
The operator->
has special semantics in the language in that, when overloaded, it reapplies itself to the result. While the rest of the operators are applied only once, operator->
will be applied by the compiler as many times as needed to get to a raw pointer and once more to access the memory referred by that pointer.
struct A { void foo(); }; struct B { A* operator->(); }; struct C { B operator->(); }; struct D { C operator->(); }; int main() { D d; d->foo(); }
In the previous example, in the expression d->foo()
the compiler will take the object d
and apply operator->
to it, which yields an object of type C
, it will then reapply the operator to get an instance of B
, reapply and get to A*
, after which it will dereference the object and get to the pointed data.
d->foo(); // expands to: // (*d.operator->().operator->().operator->()).foo(); // D C B A*
myClassIterator->APublicMethodInMyClass()
is nothing but the following:
myClassIterator.operator->()->APublicMethodInMyClass()
The first call to the overloaded operator->
gets you a pointer of some type which has an accessible (from your call-site) member function called APublicMethodInMyClass()
. The usual function look-up rules are followed to resolve APublicMethodInMyClass()
, of course, depending on whether it is a virtual or not.
There is not necessarily a temporary variable; the compiler may or may not copy the pointer returned by &(m_iterator->second)
. In all probability, this will be optimized away. No temporary objects of type MyClass
will be created though.
The usual caveats also do apply to m_iterator
-- make sure that your calls do not access an invalidated iterator (i.e. if you are using vector
for example).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With