22 votos

Punteros a elementos de std::vector y std::list

Estoy teniendo un std::vector con elementos de la clase ClassA. Además quiero crear un índice mediante un std::map<key,ClassA*> , el cual se asigna algún valor de la clave a los punteros a los elementos contenidos en el vector.

Hay ninguna garantía de que estos punteros siguen siendo válidas (y apuntan al mismo objeto) cuando los elementos se añaden al final del vector (no inserta). I. e, el siguiente código es correcta:

std::vector<ClassA> storage;
std::map<int, ClassA*> map;

for (int i=0; i<10000; ++i) {
  storage.push_back(ClassA());
  map.insert(std::make_pair(storage.back().getKey(), &(storage.back()));
}
// map contains only valid pointers to the 'correct' elements of storage

¿Cómo es la situación, si utilizo std::list en lugar de std::vector?

19voto

DumbCoder Puntos4097

Vectores - No. Debido a la capacidad de los vectores nunca se encoge, se garantiza que las referencias, los punteros, y los iteradores siendo válido aun cuando los elementos son eliminados o modificados, siempre se refieren a una posición antes de manipular los elementos. Sin embargo, las inserciones pueden invalidar las referencias, los punteros, y los iteradores.

Listas - Sí, insertar y eliminar elementos no invalida punteros, referencias, y los iteradores a otros elementos

9voto

SadSido Puntos1569

Hasta donde yo entiendo, no hay ninguna garantía de ello. La adición de elementos al vector que hará que los elementos de la re-asignación, así invalidar todos los punteros en el mapa.

6voto

Sjoerd Puntos4548

Uso std::deque! Los punteros a los elementos son estables cuando sólo push_back() se utiliza.

Nota: los Iteradores de los elementos puede ser invalidado! Punteros a elementos no.

Edit: esta respuesta explica los detalles de por qué: C++ deque del iterador invalidado después de push_front()

2voto

sbi Puntos100828

No estoy seguro si es garantizado, pero en la práctica, storage.reserve(needed_size) debe asegurarse de que no reasignaciones de ocurrir.

Pero ¿por qué no almacenar índices?
Es fácil convertir los índices de iteradores, agregándolos a comenzar iterator (storage.begin()+idx) y es fácil convertir cualquier iterador en un puntero al primer eliminar, y luego de tomar su dirección (&*(storage.begin()+idx)).

1voto

Tom Puntos13036

Sólo hacen almacenar punteros de un explícitamente eliminar los objetos cuando ya no los necesiten.

std::vector<ClassA*> storage;
std::map<int, ClassA*> map;

for (int i=0; i<10000; ++i) {
  ClassA* a = new ClassA()
  storage.push_back(a)
  map.insert(std::make_pair(a->getKey(), a))
}
// map contains only valid pointers to the 'correct' elements of storage

Iteramos.com

Iteramos es una comunidad de desarrolladores que busca expandir el conocimiento de la programación mas allá del inglés.
Tenemos una gran cantidad de contenido, y también puedes hacer tus propias preguntas o resolver las de los demás.

Powered by: