Tipo de puntero ‘this’

Como mencioné en el título, me gustaría saber sobre el tipo de 'this' puntero.

Estoy trabajando en un proyecto y observé que el tipo de puntero 'this' es "ClassName * const this" en Windows usando VC ++ 2008. Bueno, me gustaría saber cuál es la necesidad / requisito para hacer de este puntero una constante puntero. Gracias.

El tipo de este puntero es ClassName * o const ClassName * , dependiendo de si se inspecciona dentro de un método no const o const de la clase ClassName . Puntero this no es un valor l.

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

La observación que mencionaste arriba es engañosa. Puntero this no es un lvalue , lo que significa que no puede tener ClassName * const type, es decir, no es posible tener un const a la derecha de * . Los valores no significativos del tipo de puntero no pueden ser const o non-const. Simplemente no hay tal concepto en el lenguaje C ++. Lo que observaste debe ser una peculiaridad interna del comstackdor específico. Formalmente, es incorrecto.

Aquí están las citas relevantes de la especificación del lenguaje (énfasis mío)

9.3.2 El puntero este

En el cuerpo de una función miembro no estática (9.3), la palabra clave this es una expresión prvalue cuyo valor es la dirección del objeto para el que se llama a la función. El tipo de esto en una función miembro de una clase X es X *. Si la función miembro se declara const, el tipo de esto es const X *, si la función miembro se declara volátil, el tipo de esto es volátil X *, y si la función miembro se declara const volátil, el tipo de esto es const volátil X *. [Nota: por lo tanto, en una función de miembro constante, se accede al objeto para el que se llama a la función a través de una ruta de acceso const. -Finalizar nota]


No vale la pena que en el C ++ 98 / C ++ 03 varios comstackdores usaran un truco de implementación interno: interpretaron sus punteros como punteros constantes, por ejemplo, ClassName *const en un método no constante de la clase ClassName . Esto aparentemente les ayudó a asegurar la no modificabilidad de this . Se sabe que GCC y MSVC usaron la técnica. Fue un truco inofensivo, ya que a nivel del lenguaje this no era un valor y su constness era indetectable. Esa const adicional generalmente se revelaría solo en los mensajes de diagnóstico emitidos por el comstackdor.

Sin embargo, con el advenimiento de referencias rvalue en C ++ 11, fue posible detectar esta const adicional en el tipo de this . Por ejemplo, el siguiente código es válido en C ++ 11

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

Sin embargo, normalmente no se comstackrá en las implementaciones que aún utilizan el truco antes mencionado. GCC ha abandonado la técnica desde entonces. MSVC ++ todavía lo usa (a partir de VS2017), lo que impide que el código perfectamente válido anterior se compile en MSVC ++.

La const significa que no puede cambiar a lo que apunta el puntero.

 ClassName *const 

es muy diferente de

 const ClassName * 

Este último es un puntero a un objeto y el objeto no puede ser modificado (usando el puntero, de todos modos). El primero es un puntero que no se puede volver a apuntar a otro objeto (ni NULL), al menos sin recurrir a la desagradable conversión.

Por supuesto, también existe la combinación:

 const ClassName *const 

Esto sería un puntero que no puede cambiarse para apuntar a otra cosa, ni puede usarse para cambiar el objeto al que apunta.

En cuanto a por qué su comstackdor muestra this punteros como const, tiene sentido que se desanime de hacer this punto a un objeto que no sea el que comenzó.

Hubo muchas discusiones arriba y la publicación principal no presentó la respuesta correcta. Es posible que las personas no escarban los comentarios, por lo que es mejor compartirlo como puerto principal (PS).

Hice algunas investigaciones en Ubuntu así como en VC ++ pero no hay salida correcta (usando typeid(X).name ).


El tipo de este puntero para una función miembro de un tipo de clase X es X * const. Si la función miembro se declara con el calificador const, el tipo de este puntero para esa función miembro para la clase X es const X * const. Enlace de MSDN


Conceptualmente esto también es correcto, porque la función de miembro normal es “X * const”, por eso no es l-value (ya que no se puede cambiar su contenido).

Un extracto de C ++ Primer 4th ed: “En una función ordinaria de miembro nonconst , el tipo de this es un const pointer para el tipo de class . Podemos cambiar el valor al cual this apunta pero no podemos cambiar la dirección que this contiene. función de miembro, el tipo de this es un const pointer a un objeto de tipo const class . No podemos cambiar ni el objeto al que apunta ni la dirección que this contiene “. Esto significa que todo lo que VC ++ intellisense estaba mostrando es correcto.