2011-01-28 11 views
8

Al ejecutar este código C++, esperaba que la salida fuera Abc, pero era FFF, ¿por qué? ¿No está name apuntando a una constante char?const - No debería no cambiar

#include <iostream> 
int main() 
{ 
    const char* name = "Abc"; 
    name = "FFF"; 
    std::cout<<name<<std::endl; 
    return 0; 
} 
+0

que le recomendamos que lea este post sobre [const] (http://stackoverflow.com/questions/1143262/what-is-the-difference-between-const-int-const-int-const- int-const) – canardman

Respuesta

3

Con const char* name = "Abc"; le están diciendo compilador que no va a cambiar los contenidos de "ABC" por medio de name. Sin embargo, puede cambiar el puntero para señalar una ubicación de memoria diferente. Consulte esto FAQ para más detalles.

14

Sí, está apuntando a un const char como dices, pero no es un puntero constante. Estás cambiando lo que estás señalando, no el contenido de lo que estás apuntando. En otras palabras, la memoria que contiene "Abc" aún retiene los caracteres "Abc" después de reasignar el puntero.

Para un puntero constante, quiere const char* const name = "Abc";. En este caso, no compilará ya que no puede cambiar a lo que apunta el puntero.

En general, con const y punteros en C++, puede leer el nombre del tipo de derecha a izquierda para tener una idea de lo que está sucediendo. Por ejemplo, en el caso const char* const, puede leer esto como "un puntero constante a una constante de caracteres". Un poco raro, pero funciona.

0
const char* name = "Abc"; 

En realidad esto significa que el nombre es un puntero a los datos de const. Significa, son los datos que son const, no el puntero en sí. Así que es perfectamente válido si se escribe:

name = "FFF"; //ok : changing the pointer 

Sin embargo, la siguiente no se compilará:

char * const name = "Abc"; //const pointer to the non-const data! 
name = "FFF"; //error: trying to change the pointer itself! 

ver el error del compilador:

prog.cpp:5: error: assignment of read-only variable ‘name’

Véase a sí mismo aquí: http://www.ideone.com/KyNXx

0

Cuando declara una variable como

const T* ptr = /*...*/ 

Está declarando un puntero que indica que el objeto al que apunta, no el puntero, no debe cambiar. En otras palabras, es un "puntero a una T que es const".

Si desea hacer que sea imposible para reasignar el puntero, puede escribir

T* const ptr = /*...*/ 

Esto es ahora un puntero inmutable a una T, que puede ser modificado.

Se pueden combinar estos juntos como esto:

const T* const ptr = /*...*/ 

Para obtener un puntero a una inmutable T. inmutable

Como un toque divertido, por lo general puede determinar qué partes de un par de puntero/puntiaguda puede ser modificado leyendo el tipo de derecha a izquierda. Pruébalo en lo de arriba y mira lo que obtienes.

0

En primer lugar, const solo se comprueba en tiempo de compilación. Si se compila, todas las operaciones se realizarán normalmente en el tiempo de ejecución.

En su ejemplo, const se aplica al contenido señalado por name. Así que puedes cambiar el puntero, pero no el contenido.

strcpy(name, "FFF"); 

se rechazarán, pero no cambiarán el puntero como usted lo hizo.

6

const char * name = "Abc"; -> No const pointer-> name, pero los datos (Abc) son constantes

name = "FFF" -> cambiando el puntero (nombre) para que apunte a FFF.

char *p    = "Hello";   // non-const pointer, 
             // non-const data 
const char *p  = "Hello";   // non-const pointer, 
             // const data 
char * const p  = "Hello";   // const pointer, 
             // non-const data 
const char * const p = "Hello";   // const pointer, 
             // const data 
+1

Esto es (una razón, la otra es la regla typdef) por la que prefiero poner siempre la const a la derecha. Hace que esta regla sea más fácil de analizar. 'char const * const p'. Lectura de derecha a izquierda: 'p es una" constante * "a" constante char "' –

+0

Por alguna razón, nunca tuve problemas para leer 'const char *' correctamente. Siempre sintió naturalmente que 'const' pertenece a' char'. – Mephane

+1

@Mephane: Claro. Pero ahora inserte un typedef y vea en qué se convierte el significado (si no tiene cuidado, cambia (cuando const es el primero)) pero es consistente cuando const se coloca a la izquierda del objeto. –

2

de hecho la sintaxis correcta es más

char const * pName; 

porque const palabra clave se aplica a saber, la parte en el lado izquierdo.

si quieres un poitner const a un const char se escribirían:

char const * const pName; 

y un puntero constante a un int;

int * const pInt; 

PD: pero todavía escribo la const en el comienzo de la línea cada vez que puedo, un habito anclada ;-)

3

Es un problema conocido con const y de habla inglesa.

La sintaxis permite tanto:

  • const T
  • T const

y ambos tienen el mismo significado.

sin embargo, resulta complicado una vez que se lanza un puntero en la mezcla:

  • const T* debe leerse (const T)*
  • T const* debe leerse (T const)*
  • T* const debe leerse (T*) const

Por eso soy un experto en usar siempre const en el derecho inmediato del objeto. Esto es más consistente.

Tenga en cuenta que el mismo problema se puede encontrar con typedef, vamos a definir typedef T* pointer:

  • const pointer significa T* const, no const T* (como una macro implicaría)
  • pointer const significa T* const, como la sustitución textual

Si toma el hábito de poner el const después del nombre, y no b antes como un adjetivo en inglés, entonces no caerás en esas trampas.

+0

¿No se leería 'T * const' como' T (* const) 'como' puntero constante a T'? – Xeo

0

Las cadenas literales "Abc" y "FFF" son constante, pero name es una variable (puntero a datos constantes). Simplemente ha cambiado la variable para apuntar a diferentes datos constantes.

Además, en este caso los datos eran necesariamente constantes, un puntero a datos constantes solo significa que los datos no se pueden modificar desmarcando ese puntero, los datos también se pueden modificar directamente o mediante un puntero diferente. P.ej.

int i = 0 ; 
const int* p = &i ; 
i++ ; // valid 
(*p)++ // error. 
Cuestiones relacionadas