Подтвердить что ты не робот

Тип указателя 'this'

Как упоминалось в названии, я хотел бы узнать о типе указателя 'this'.

Я работаю над проектом, и я заметил, что тип указателя 'this' "ClassName * const this" для Windows с помощью VС++ 2008. Ну, я хотел бы знать, в чем заключается необходимость/требование, чтобы этот указатель был постоянным указатель. Спасибо.

4b9b3361

Ответ 1

Тип этого указателя есть либо ClassName *, либо const ClassName *, в зависимости от того, проверяется ли он внутри метода non-const или const класса ClassName. Указатель this не является lvalue.

class ClassName {
  void foo() {
    // here `this` has `ClassName *` type
  }

  void bar() const {
    // here `this` has `const ClassName *` type
  }
};

Наблюдение, о котором вы говорили выше, вводит в заблуждение. Указатель this не является значением lvalue, что означает, что он не может иметь тип ClassName * const, т.е. Он не может иметь const справа от *. Не-lvalues ​​типа указателя не может быть const или не const. Просто нет такой концепции на языке С++. То, что вы наблюдали, должно быть внутренним причудом конкретного компилятора. Формально это неверно.

Вот соответствующие цитаты из спецификации языка (выделение)

9.3.2 Этот указатель

В теле нестатической (9.3) функции-члена ключевое слово this выражение prvalue, значение которого является адресом объекта для который вызывается функцией. Тип этого в членной функции класс X является X *. Если функция-член объявлена ​​const, тип это const X *, если функция-член объявлена ​​изменчивой, тип этого является изменчивым X *, и если объявлена ​​функция-член const volatile, тип этого - константа volatile X *. [Примечание: таким образом, в функция-член const, объект, для которого вызывается функция доступен через путь доступа к const. -end note]


Не стоит ничего, что в С++ 98/С++ 03 раз несколько компиляторов использовали внутренний реализационный трюк: они интерпретировали свои указатели this как постоянные указатели, например. ClassName *const в непостоянном методе класса ClassName. Это, по-видимому, помогло им обеспечить немогитильность this. GCC и MSVC, как известно, использовали эту технику. Это был безобидный трюк, поскольку на уровне языка this не было lvalue, и его константа была необнаруживаема. Этот дополнительный const обычно обнаруживается только в диагностических сообщениях, выпущенных компилятором.

Однако с появлением ссылок rvalue в С++ 11 стало возможным обнаружить этот дополнительный const по типу this. Например, следующий код действителен в С++ 11

struct S
{
  void foo() { S *&&r = this; }
};

Однако он, как правило, не сможет скомпилировать в реализациях, которые все еще используют вышеупомянутый трюк. С тех пор GCC отказался от этой техники. MSVС++ все еще использует его (как и VS2017), что предотвращает компиляцию вышеуказанного полностью корректного кода в MSVС++.

Ответ 2

Константа означает, что вы не можете изменить то, на что указывает указатель.

ClassName *const

сильно отличается от

const ClassName *

Последний является указателем на объект, и объект не может быть изменен (используя указатель, во всяком случае). Первый - это указатель, который нельзя переопределить на другой объект (или NULL), по крайней мере, не прибегая к неприятному кастингу.

Конечно, есть и комбинация:

const ClassName *const

Это будет указатель, который нельзя изменить, чтобы указать на что-то еще, и не может использоваться для изменения объекта, на который он указывает.

Что касается того, почему ваш компилятор показывает указатели this как const, имеет смысл, что вам не рекомендуется указывать this на объект, отличный от того, с которого он начинался.

Ответ 3

Было много обсуждений выше, и главный пост не дал правильного ответа. Люди могут не копать комментарии, поэтому лучше использовать их в качестве основного порта (PS).

Я провел некоторое исследование на Ubuntu, а также на VС++, но нет правильного вывода (используя typeid(X).name).


Тип этого указателя для функции-члена класса X, является X * const. Если функция-член объявлена ​​с помощью спецификатора const, тип этого указателя для этой функции-члена для класса X является const X * const. Ссылка MSDN


Концептуально это также верно, поскольку для нормальной функции-члена есть "X * const", поэтому он не является l-значением (поскольку вы не можете изменить его содержимое).

Ответ 4

Выдержка из С++ Primer 4th ed: "В обычной функции члена nonconst тип this - это const pointer для типа class. Мы можем изменить значение, на которое this указывает но не может изменить адрес, который имеет this. В функции-члене const тип this - это объект const pointer to const class. Мы не можем изменить ни объект, для которого this точки или адрес, который соответствует this." Это означает, что отображение VС++ intellisense правильное.