0

I have simple code

#include <iostream>
#include <set>

using namespace std;
class Example
{
    string name;
public:
    Example(string name)
    {
        this -> name = name;
    }
    string getName() const {return name;}
};
bool operator<(Example a, Example b)
{
    return a.getName() < b.getName();
}
int main()
{
    set<Example> exp;
    Example first("first");
    Example second("second");
    exp.insert(first);
    exp.insert(second);
    for(set<Example>::iterator itr = exp.begin(); itr != exp.end(); ++itr)
    {
        //cout<<*itr.getName(); - Not working
        cout<<(*itr).getName()<<endl;
    }

}

I wonder why *itr.getName() doesn't work but (*itr).getName() works fine. What is the difference between *itr and (*itr) in this case?

JaMiT
  • 14,422
  • 4
  • 15
  • 31
sizeof
  • 3
  • 2
  • 2
    https://en.cppreference.com/w/cpp/language/operator_precedence – Useless Oct 23 '22 at 21:32
  • 1
    Questions that asked something different than this one, but that have the same answer: [Vector push back operation with pointer](https://stackoverflow.com/questions/48014897/), [Delete list element from class](https://stackoverflow.com/questions/23544797/), [How can I call a method of an object in a list iterator in C++?](https://stackoverflow.com/questions/74116507/), [Why can't I dereference a pointer to an object that's an array-element using the indirection operator?](https://stackoverflow.com/questions/39030947/) – JaMiT Oct 23 '22 at 22:17

2 Answers2

2

C++ has rules for operator precedence. According to these rules, the member access operator . has higher precedence than the dereference operator unary *.

Therefore, the expression

*itr.getName()

Is interpreted as though it had the parentheses:

*(itr.getName())

That is, it tries to evaluate itr.getName() and then dereference that. itr doesn't have any such member getName, so this doesn't compile. However, you can use the parentheses yourself to write:

(*itr).getName()

This dereferences itr first, and then accesses the getName member of the resulting Example. You can also use the dereference-and-member-access operator -> as follows:

itr->getName() // Same meaning as (*itr).getName()
Nathan Pierson
  • 5,461
  • 1
  • 12
  • 30
  • Glad I could help! If you feel this answers your question, please go ahead and hit the checkmark next to this answer to indicate that. – Nathan Pierson Oct 23 '22 at 21:44
0

It's all about operator precedence.

The * (pointer/indirection) operator has a lower precedence than the . (member access) operator, therefore when doing *itr.getName(), the compiler will first try to access getName as a property of itr, and then attempt to dereference the value returned by getName(), which becomes the value of the expression.

In short, your first attempt is equivalent to:

auto name = iter.getName();
return *name;

Your second attempt works because of the brackets because (*itr) will first derefernce the pointer, then .getName() will call getName on whatever the pointer was pointing to. This all works because of the bracket.

However, C++ also has another operator called the arrow operator (->), which allows us to directly access a member property of a pointee. Therefore, you could also use:

auto name = iter->getName();
smac89
  • 39,374
  • 15
  • 132
  • 179