Is the following C++ code equiv? (in a smart pointer implementation)
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>
cons开发者_高级运维t 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!
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.
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.
精彩评论