que punteros puntero parametros operaciones funciones ejemplos ejemplo dev con como cadenas aritmetica apuntadores c++ pointers vector const operator-precedence

c++ - parametros - ¿Por qué se puede cambiar el elemento desreferenciado en el vector const de punteros int?



punteros en c ejemplos (4)

No estoy seguro del verdadero significado de const vector<int *> así que compilé el código siguiente para tener una idea, pero ahora estoy más confundido.

vector<int *> v; int x = 1, y = 2; v.push_back(&x); v.push_back(&y); const vector<int *> w = v; w[0] = &y; //failed. Element is a constant pointer? *(w[0]) ++; //failed. Element pointer references to constant value?

Si me hubiera detenido aquí, habría supuesto que const vector<int *> es un vector de const int * const , pero luego probé lo siguiente, lo cual contradice claramente esa suposición.

*(w[0]) += 3; //passed. Value not constant? *(w[0]) = 20; //passed. Why...

Ahora *(w[0]) por razones desconocidas para mí obviamente trata ++ y += y la asignación de manera diferente. Me convencí de que el const vector solo declara un objeto constante de la clase vector y que los resultados anteriores podrían depender de la implementación real de la sobrecarga del operador de vector clase vector . Pero no puedo entender esto. ¿Alguien puede ayudar a explicar, por favor?

Si es relevante, usé g ++ 4.2 en una Mac.


¿Por qué se puede cambiar el elemento desreferenciado en el vector const de punteros int?

Para const vector<int *> , el elemento sería const pointer a non- const , es decir, int * const , por lo que puede modificar el objeto apuntado por el puntero, pero no el puntero en sí.

De acuerdo con Precedencia del operador , el operador de incremento postfix tiene una precedencia mayor que el operator* , entonces *(w[0]) ++; es equivalente a

* ((w[0]) ++);

El incremento en el puntero se realiza al principio, luego falla. w[0] = &y; también está tratando de modificar el puntero, por lo que también falla.

Por otro lado, (*w[0]) ++; (es decir, incremento en la punta) estaría bien. Y las siguientes afirmaciones también están bien, porque ambas están modificando los objetos apuntados por el puntero, no los punteros.

*(w[0]) += 3; //passed. *(w[0]) = 20; //passed.


Es una cuestión de precedencia del operador .

Cuando lo hace *(w[0]) ++ , intenta modificar el puntero .

Cuando lo hace *(w[0]) += 3 , modifica los datos apuntados por el puntero.


const vector<T> permite acceder a sus elementos como T const & ( es decir, const T & ). En este caso, T es int * , entonces esto es int * const & , una referencia constante a un puntero que apunta a un int . El puntero es constante, pero el int no lo es.

El tipo del vector debería haber sido vector<int const *> ( es decir, vector<const int*> ) en cuyo caso se accedería a los elementos a través de int const * const & .

En pocas palabras, la constness es transitiva con plantillas pero no con punteros. Y si pones punteros en plantillas, obtienes un poco de ambos comportamientos.


w es un const vector<int *> . El calificador const se aplica al vector. Por lo tanto, la función miembro miembro correspondiente se usará para el operator[] :

const_reference operator[]( size_type pos ) const;

Como el vector está const qualificado y contiene elementos de tipo int * (y no const int * ), el tipo de la expresión w[0] es int * const& (en lugar de const int *& ). Es decir, es una referencia a un puntero constante a un int y no a un puntero a una constante int : la constness se aplica al puntero mismo, no a los datos que se apuntan.

Al hacer *(w[0]) += 3 no está modificando el valor del puntero que devuelve el vector (que es const ), sino el valor al que apunta este puntero . Como este puntero es de tipo int * const (y no const int * ), puede modificar lo que señala, por lo que funciona. Sin embargo, hacer w[0] = &y está realizando una asignación en un puntero constante, por lo que no se compila.