Является ли следующий код C ++ эквивалентным? (в реализации интеллектуального указателя) - PullRequest
2 голосов
/ 21 января 2010

код 1:

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

Код 2:

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

Была ли когда-нибудь какая-либо ситуация, когда эти два блока кода будут делать разные вещи? Спасибо!

Ответы [ 2 ]

7 голосов
/ 21 января 2010

Была ли когда-нибудь ситуация, когда эти два блока кода будут делать разные вещи?

Да, когда вы используете метод const. В настоящее время один с me вызывает неопределенное поведение. И вот почему:

Как вы знаете, когда вы вызываете функцию-член, существует неявный указатель this. Указатель this равен const, когда функция помечена как const. Вот пример:

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

    int i;
};

Неявно, компилятор генерирует (кстати, это упрощенно):

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

Итак, эти два тела одинаковы?

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

// and

this->i = 1;

Ответ - , это зависит , и, как было сказано ранее, это зависит от const -ности функции. В функции, отличной от const, они одинаковы:

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

    // ...

    this->i = 1;
}

Но в функции const:

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
}

В итоге мы убираем const. Так что нет, они не всегда одинаковы. Это опасность для броска в стиле C: он найдет способ. Кстати, отбрасывание const само по себе не является неопределенным поведением; это - модификация упомянутой переменной, которая делает это.

Однако в вашем вопросе есть проблема: ваш код не должен компилироваться. Как и в приведенном выше коде, в вашем методе const вы не сможете изменить reference_.

Это отличается, если reference_ равен mutable, что, я полагаю, могло бы быть (при условии, что вы дали нам скомпилированный код.) В этом случае я не уверен, приводит ли первый пример к неопределенному поведению, так как это было mutable во-первых. Я бы не стал рисковать.

2 голосов
/ 21 января 2010

Более или менее все, что сказал GMan, за исключением ссылок_, не должно быть изменчивым. Это также может быть объект, у которого переопределенный оператор ++ () является функцией-константой.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...