Тип этого указателя: 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 ++.