• Create Account

### #Actualfrob

Posted 26 August 2013 - 04:35 PM

What is this fad of people using 'this->member' all over the place instead of just referring to members the normal way? It makes my teeth itch.

It's easier to use intelisense with.

True, but there are also a few minor side effects.

First is that if the class overrides operator-> it will use that instead. This is a fairly rare thing, but something to consider.

Second is that it has the potential to cause some unnecessary trips to memory. Most optimizers will strip that away, but as this is the "General Programming" forum rather than "For Beginners", we should not be over-reliant on the optimizer. I've worked on several systems over the years (Nintendo DS, PalmOS, etc.) that when encountered would dereference the this pointer and follow it rather than use the information already loaded in registers.

My current studio includes it is in our programming style guide as a restricted practice. I flag it in code reviews as an error when I see it.

As pointed out above, overriding -> has no effect on this.

That is what makes it confusing, and one of the reasons to avoid it.

The arrow operator is not overriden very often, but it is one of those "gotcha" areas of C++.  It generally works the way programmers expect it to work, but there is some subtlety in the drill-down behavior when operator overloading is involved.

Contrived example to demonstrate:

#include <iostream>

struct Concrete {
void foo() { std::cout << "Concrete::foo\n"; }
};
struct Proxy {
Concrete *a;
void foo() { std::cout << "Proxy::foo\n"; }
Concrete* operator->() { return a; }
};
struct Proxy2 {
Proxy *b;
void foo() { std::cout << "Proxy2::foo\n"; }
Proxy& operator->() { return *b; }

void RunFoo() {
foo(); // Calls Proxy2::foo
this->foo();  // QUIZ #1:  Which foo() is called?
(*this).operator->()->foo(); // QUIZ #2: Which foo() is called?
}
};
int main()
{
Concrete a;
Proxy b = { &a };
Proxy2 c = { &b };
c.RunFoo();
c->foo(); // QUIZ #3: Which foo() is called?
}


The answers are not surprising at all when you stop to think about them.

The problem is that you need to stop and think about them.

: edit: code box got messed up, fixing formatting.

### #2frob

Posted 26 August 2013 - 04:29 PM

What is this fad of people using 'this->member' all over the place instead of just referring to members the normal way? It makes my teeth itch.

It's easier to use intelisense with.

True, but there are also a few minor side effects.

First is that if the class overrides operator-> it will use that instead. This is a fairly rare thing, but something to consider.

Second is that it has the potential to cause some unnecessary trips to memory. Most optimizers will strip that away, but as this is the "General Programming" forum rather than "For Beginners", we should not be over-reliant on the optimizer. I've worked on several systems over the years (Nintendo DS, PalmOS, etc.) that when encountered would dereference the this pointer and follow it rather than use the information already loaded in registers.

My current studio includes it is in our programming style guide as a restricted practice. I flag it in code reviews as an error when I see it.

As pointed out above, overriding -> has no effect on this.

Yes it has no effect.

That is what makes it confusing, and one of the reasons to avoid it.

The arrow operator is not overriden very often, but it is one of those "gotcha" areas of C++.  It generally works the way programmers expect it to work, but there is some subtlety in the drill-down behavior when operator overloading is involved.

Contrived example to demonstrate:

#include <iostream>

struct Concrete {
void foo() { std::cout << "Concrete::foo\n"; }
};
struct Proxy {
Concrete *a;
void foo() { std::cout << "Proxy::foo\n"; }
Concrete* operator->() { return a; }
};
struct Proxy2 {
Proxy *b;
void foo() { std::cout << "Proxy2::foo\n"; }
Proxy& operator->() { return *b; }

void RunFoo() {
foo(); // Calls Proxy2::foo
this->foo();  // QUIZ #1:  Which foo() is called?
(*this).operator->()->foo(); // QUIZ #2: Which foo() is called?
}
};
int main()
{
Concrete a;
Proxy b = { &a };
Proxy2 c = { &b };
c.RunFoo();
c->foo(); // QUIZ #3: Which foo() is called?
}


The answers are not surprising at all when you stop to think about them.

The problem is that you need to stop and think about them.

: edit: code box got messed up, fixing formatting.

### #1frob

Posted 26 August 2013 - 04:28 PM

What is this fad of people using 'this->member' all over the place instead of just referring to members the normal way? It makes my teeth itch.

It's easier to use intelisense with.

True, but there are also a few minor side effects.

First is that if the class overrides operator-> it will use that instead. This is a fairly rare thing, but something to consider.

Second is that it has the potential to cause some unnecessary trips to memory. Most optimizers will strip that away, but as this is the "General Programming" forum rather than "For Beginners", we should not be over-reliant on the optimizer. I've worked on several systems over the years (Nintendo DS, PalmOS, etc.) that when encountered would dereference the this pointer and follow it rather than use the information already loaded in registers.

My current studio includes it is in our programming style guide as a restricted practice. I flag it in code reviews as an error when I see it.

As pointed out above, overriding -> has no effect on this.

Yes it has no effect.

That is what makes it confusing, and one of the reasons to avoid it.

The arrow operator is not overriden very often, but it is one of those "gotcha" areas of C++.  It generally works the way programmers expect it to work, but there is some subtlety in the drill-down behavior when operator overloading is involved.

Contrived example to demonstrate:

#include <iostream>

struct Concrete {
void foo() { std::cout << "Concrete::foo\n"; }
};
struct Proxy {
Concrete *a;
void foo() { std::cout << "Proxy::foo\n"; }
Concrete* operator->() { return a; }
};
struct Proxy2 {
Proxy *b;
void foo() { std::cout << "Proxy2::foo\n"; }
Proxy& operator->() { return *b; }

void RunFoo() {
foo(); // Calls Proxy2::foo
this->foo();  // QUIZ #1:  Which foo() is called?
(*this).operator->()->foo(); // QUIZ #2: Which foo() is called?
}
};
int main()
{
Concrete a;
Proxy b = { &a };
Proxy2 c = { &b };
c.RunFoo();
c->foo(); // QUIZ #3: Which foo() is called?
}

The answers are not surprising at all when you stop to think about them.

The problem is that you need to stop and think about them.

PARTNERS