Es decir que si cambio un elemento de la lista (de la STL list) por fuera de ella este cambio se vea reflejado dentro de la lista (o listas que tengan el elemento insertado) sin necesidad de recorrerla y hacer el cambio "manualmente". ¿Esto se podría hacer con un apuntador(*) o una referencia(&) o algo así?
-
Sería de agradecer que pusieses un código de ejemplo que reprodujese el problema – eferion Aug 21 '18 at 06:07
1 Answers
¿Esto se podría hacer con un apuntador(*) o una referencia(&)?
Si y no.
Puntero (*
)
Con una lista de punteros puedes, efectivamente, modificar el valor al que el apuntador (puntero) apunta pero el elemento de la lista (el apuntador) no será modificado, sólo será modificado aquello a lo que apunta:
template <typename T>
using lista_puntero = std::list<T *>;
int a = 1, b = 2, c = 3;
lista_puntero<int> lp{&a, &b, &c};
for (const auto &v : lp)
std::cout << "Direccion: " << v << " Valor: " << *v << '\n';
a += 3;
b += 2;
c += 1;
std::cout << '\n';
for (const auto &v : lp)
std::cout << "Direccion: " << v << " Valor: " << *v << '\n';
El código anterior muestra lo siguiente1:
Direccion: 0x7ffd4adfe81c Valor: 1 Direccion: 0x7ffd4adfe818 Valor: 2 Direccion: 0x7ffd4adfe814 Valor: 3 Direccion: 0x7ffd4adfe81c Valor: 4 Direccion: 0x7ffd4adfe818 Valor: 4 Direccion: 0x7ffd4adfe814 Valor: 4
Como puedes ver, el valor almacenado en la lista no cambia, así que no cumple tu primera premisa: "si cambio un elemento de la lista por fuera de ella este cambio se vea reflejado dentro de la lista", esto sucede porque el apuntador (puntero) y el dato apuntado no son el mismo elemento. Sin embargo sí que se ha cambiado el valor al que apunta el dato apuntado por el puntero almacenado en la lista.
Referencia (&
)
El lenguaje C++ no permite colecciones de referencias2, pero podemos usar una envoltura de referencia: std::reference_wrapper
:
template <typename T>
using lista_referencia = std::list<std::reference_wrapper<T>>;
int a = 1, b = 2, c = 3;
lista_referencia<int> lr{a, b, c};
for (const auto &v : lr)
std::cout << "Direccion (wrapper): " << &v << " Valor: " << v << '\n';
a += 3;
b += 2;
c += 1;
std::cout << '\n';
for (const auto &v : lr)
std::cout << "Direccion (wrapper): " << &v << " Valor: " << v << '\n';
El código anterior muestra lo siguiente3:
Direccion (wrapper): 0x684170 Valor: 1 Direccion (wrapper): 0x684190 Valor: 2 Direccion (wrapper): 0x683ed0 Valor: 3 Direccion (wrapper): 0x684170 Valor: 4 Direccion (wrapper): 0x684190 Valor: 4 Direccion (wrapper): 0x683ed0 Valor: 4
La envoltura de referencia hace más sencillo el código y sigue tu primera premisa "si cambio un elemento de la lista por fuera de ella este cambio se vea reflejado dentro de la lista" sin necesidad de des-referenciar el valor (sin hacer *v
) ni almacenar punteros (no necesitamos el &variable
al añadir datos a la lista), pero sigue siendo un truco: en el fondo la envoltura no cambia pese a que el valor al que referencia sí que cambie.
- Compilado en Wandbox usando GCC 9.0.0 201808, los valores de los punteros pueden variar en cada ejecución.
- Para saber el motivo detrás de esta limitación lee esta respuesta.
- Compilado en Wandbox usando GCC 9.0.0 201808, los valores de los punteros pueden variar en cada ejecución.
- 44,474
- 6
- 44
- 82