views:

96

answers:

2

Code 1:

template<class T>
const PtrInterface<T>*
PtrInterface<T>::newRef() const {
  PtrInterface<T>* me = (PtrInterface<T>*) this;
  ++me->references_;
  //++this->references_;
  return this;
} 

Code 2:

template<class T>
const PtrInterface<T>*
PtrInterface<T>::newRef() const {
  //PtrInterface<T>* me = (PtrInterface<T>*) this;
  //++me->references_;
  ++this->references_;
  return this;
}

Is there ever any situation where these two blocks of code will do different things? Thanks!

+6  A: 

Is there ever any situation where these two blocks of code will do different things?

Yes, when you are in a const method. Currently, the one with me invokes undefined behavior. Here's why:

As you know, when you call a member function, there is an implicit this pointer. The this pointer is const when a function is marked const. Take this for example:

struct foo
{
    void method1(void);
    void method2(void) const;

    int i;
};

Implicitly, the compiler generates (by the way, this is simplified):

void foo::method1(foo* this); 
void foo::method2(const foo* this) const;

So, are these two bodies the same?

foo* me = (foo*)this;
me->i = 1;

// and

this->i = 1;

The answer is it depends, and as stated earlier, it's dependent on the const-ness of the function. In a non-const function, they are the same:

void foo::method1(foo* this)
{
    foo* me = (foo*)this; // this cast is redundant
    me->i = 1;

    // ...

    this->i = 1;
}

But in a const function:

void foo::method2(const foo* this) const
{
    foo* me = (foo*)this; // uh-oh! acts like const_cast
    me->i = 1; // modifying a const_cast'd variable is undefined behavior

    // ...

    this->i = 1; // wouldn't compile
}

We end up stripping the const away. So, no, they aren't always the same. This is the peril of the C-style cast: it will find a way. By the way, casting const away in itself isn't undefined behavior; it's the modification of said variable that does it.

There is a sticky problem in your question though: your code shouldn't compile. Like in the commented code above, in your const method you shouldn't be able to modify reference_.

This is different if reference_ is mutable, which I'm guessing it might be (assuming you gave us compilable code.) In this case, I'm not certain if the first sample leads to undefined behavior, since it was mutable in the first place. I wouldn't take the chance though.

GMan
nice edit but last answer was short and sweet :) It diff to go thru long answer without losing focus :)
Yogesh Arora
@Yogesh: I felt the old one was harder to follow, this one is step-by-step "don't do it". :P
GMan
+1  A: 

More or less everything GMan has said, except references_ need not be mutable. It could also be an object which has overridden operator++() to be a const member function.

Dagititis
True, though that's even uglier than I would imagine.
GMan