开发者

Is the following C++ code equiv? (in a smart pointer implementation)

开发者 https://www.devze.com 2022-12-17 09:49 出处:网络
Code 1: template<class T> const PtrInterface<T>* PtrInterface<T>::newRef() const { PtrInterface<T>* me = (PtrInterface<T>*) this;

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.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号