Тип указателя this - PullRequest
       19

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

30 голосов
/ 20 мая 2011

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

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

Ответы [ 4 ]

47 голосов
/ 20 мая 2011

Тип этого указателя: ClassName * или const ClassName *, в зависимости от того, проверяется ли он внутри неконстантного или константного метода класса 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 справа от *.Не-значения типа указателя не могут быть постоянными или неконстантными.В языке C ++ такого понятия просто нет.То, что вы наблюдали, должно быть внутренней прихотью конкретного компилятора.Формально это неверно.

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

9.3.2. Указатель this

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


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

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

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

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

3 голосов
/ 20 мая 2011

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

ClassName *const

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

const ClassName *

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

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

const ClassName *const

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

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

1 голос
/ 24 февраля 2014

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

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


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


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

0 голосов
/ 27 мая 2011

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

...