2010-02-05 12 views
5

Tengo una clase llamada Spring en un sistema de partículas. El constructor se ve como:Referencia al elemento en el vector 2d (C++)

Spring(Particle& _a, Particle& _b); 

Y tengo un vector de Partículas y utilizo

Spring mySpring = Spring(myParticles.at(j),myParticles.at(j+1)); 

dentro de un bucle para agregar una fuerza elástica entre dos partículas. Todo funciona bien hasta ahora. Sin embargo, quiero usar un vector 2d de Partículas. Es decir:

Spring mySpring = Spring(myParticles.at(i).at(j),myParticles.at(i).at(j+1)); 

Y no consigo una referencia a la partícula. En el primer ejemplo, cada vez que cambio la partícula en mi clase de primavera, la partícula en el vector cambia. En el segundo ejemplo, los cambios son solo locales. ¿Cómo puedo cambiar las partículas en el Vector 2D?

EDIT: trato de hacer algunas cosas claras:

tengo algunos sistemas de partículas y cada uno de ellos consta de un número de partículas. Cada partícula solo debería interactuar con las otras partículas que están en el mismo sistema que ella. Por lo tanto, tengo un vector de sistemas de partículas con cada sistema de partículas como vector de objetos de partículas. (Eso hace que el vector 2d). La primera dimensión (i) es el sistema, la segunda (j) la partícula individual. Las partículas en el sistema interactúan entre sí (colisionan, evitan, lo que sea ...) y cambian sus posiciones. Y el vector se "actualiza". (Es decir, la referencia funciona).

Sin embargo, tengo un segundo (1d) vector de fuerzas de resorte. La fuerza del resorte también se usa para actualizar las posiciones de las partículas. Mi constructor hace lo siguiente:

Spring::Spring(Particle& _a, Particle& _b) { 
    a=&_a; 
    b=&_b; } 

Con A y B siendo Partículas *. Así que guardo punteros a dos partículas en el vector 2d. Otra función Spring.doSpring() cambia las posiciones de las partículas.

a->pos.x=300; 

o

a->velocity+=something.. 

En el primer ejemplo que he publicado utilicé sólo un sistema de partículas y así que no había necesidad de un vector 2d. Y todo funciona bien Las partículas en el vector se actualizan. Pero con el segundo ejemplo mi programa se ejecuta pero de alguna manera no importa lo que haga la función doSpring, las partículas en el vector 2d no se actualizan.

+0

¿Cómo declara "myParticles"? – coelhudo

+0

Oye, un consejo de http://www.drdobbs.com/cpp/184401863: "No overlegislate la denominación, pero sí utiliza una convención de nomenclatura consistente: solo hay dos cosas que debes hacer: a) nunca utilizar" nombres descuidados " , "unos que comienzan con un guión bajo o que contienen un doble guión bajo"; Palabras de Herb Sutter y Andrei Alexandrescu – coelhudo

Respuesta

0

Si entiendo correctamente, ¿desea crear una matriz 2D de Partículas usando std::vector?

Si es así, puede declararlo como: std::vector<std::vector<Particle> >. Incluso podría usar la nomenclatura [][] para acceder a los elementos. (peligro Robinson! No hay límite de comprobación durante el uso de este operador)

Sin embargo, si esta matriz 2D contendrá todo ceros, entonces puede ser aceptable utilizar un map con índices como llaves.

+0

A juzgar por su código ('.at (i) .at (j)'), ya está usando un vector de vectores. –

+0

A juzgar por los ejemplos anteriores, esto parece exactamente lo que ya está tratando de hacer (la parte "at (...). At (...)"). – rjnilsson

1

Creo que this series de C++ Preguntas frecuentes Lite debería ayudar.

No se debe confundir con el encabezado de "sobrecarga del operador".Definitivamente deberías leer 13.10, 13.11 y 13.12 desde allí.

5

Lo que está haciendo se ve bien - el código siguiente, se crea un vector "2D" e ilustra que el .at() al() constructo te da una referencia:

#include <vector> 
#include <iostream> 
using namespace std; 

int main() { 
    vector <vector<int> > vi; 
    vi.push_back(vector <int>()); 
    vi.at(0).push_back(42); 
    cout << vi.at(0).at(0) << endl; // prints 42 
    vi.at(0).at(0) = 666; 
    cout << vi.at(0).at(0) << endl; // prints 666 
} 
6

Uno de los más. problemas comunes que toman referencias/punteros a los elementos dentro de los vectores es la reasignación. Si push_back, por ejemplo, es posible que el vector exceda su capacidad, asigne un nuevo bloque de memoria, copie todo, luego libere el bloque anterior. Si ha tomado referencias o punteros a elementos dentro del vector, estos aún apuntan al antiguo bloque, ahora memoria muerta, ¡y es un error grave!

Así que supongo que su efecto de partículas sigue agregando nuevas partículas a su vector de partículas, lo que en algún momento hace que el vector se reasigne cuando excede la capacidad. Sin embargo, los punteros almacenados por la clase Spring no se actualizan, por lo que apuntan a la memoria inactiva y no tienen ningún efecto sobre la partícula real, que el vector movió a otra parte.

No tome una referencia o un puntero a un elemento dentro de un vector. Utilice un vector de punteros, una lista o algún otro contenedor que no vaya a barajar las direcciones de memoria de los elementos reales. Si es necesario, utilice iteradores para elementos dentro de un vector. En las compilaciones de depuración, suponiendo que tiene una implementación de STL comprobada, recibirá una alerta de depuración si accede al elemento a través del iterador después de que el vector se reasigne.

+1

Pero, ¿eso no causaría punteros nulos que causarían la falla de la aplicación? Debido a que mi aplicación no falla, los elementos simplemente no se actualizan. Sin embargo, esa es una gran respuesta, no pensé en la reasignación. – hrst

+0

No, nada se establece en un puntero nulo: el vector no conoce los punteros en la clase Spring, por lo que nunca hace ningún intento de cambiarlos. Los punteros * no son * modificados o nulos, simplemente apuntan a una ubicación de memoria inactiva. Debido a que la memoria está probablemente en algún lugar dentro de su proceso, se permiten las lecturas y escrituras, a pesar de que probablemente esté corrompiendo la memoria de su aplicación. – AshleysBrain

Cuestiones relacionadas