2010-02-05 11 views
5

Ho una classe chiamata Spring in un sistema di particelle. Il costruttore assomiglia:Riferimento all'elemento nel vettore 2D (C++)

Spring(Particle& _a, Particle& _b); 

E ho un vettore di particelle e utilizzare

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

all'interno di un ciclo per aggiungere una forza elastica fra due particelle. Tutto funziona bene finora. Tuttavia, voglio usare un vettore 2D di particelle. Cioè:

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

E non ottengo un riferimento alla particella. Nel primo esempio, ogni volta che cambio la particella nella mia classe primaverile, la particella nel vettore viene cambiata. Nel secondo esempio le modifiche sono solo localmente. Come posso cambiare le particelle nel vettore 2D?

EDIT: provo a fare alcune cose chiare:

ho alcuni sistemi particellari e ciascuno di essi è costituito da un numero di particelle. Ogni particella dovrebbe interagire solo con le altre particelle che si trovano nello stesso sistema di se stesso. Quindi ho un vettore di sistemi di particelle con ciascun sistema di particelle che è un vettore di oggetti particellari. (Questo rende il vettore 2D). La prima dimensione (i) è il sistema, la seconda (j) la particella individuale. Le particelle nel sistema interagiscono tra loro (si scontrano, evitano, qualunque cosa ..) e le loro posizioni cambiano. E il vettore viene "aggiornato". (Cioè, il riferimento funziona).

Tuttavia, ho un secondo vettore (1d) di forze elastiche. Anche la forza della molla viene utilizzata per aggiornare le posizioni delle particelle. mio costruttore effettua le seguenti operazioni:

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

Con A e B sono particelle *. Quindi memorizzo i puntatori a due particelle nel vettore 2D. Un'altra funzione Spring.doSpring() modifica le posizioni delle particelle.

a->pos.x=300; 

o

a->velocity+=something.. 

Nel primo esempio ho postato ho usato solo un sistema di particelle e quindi non c'era bisogno di un vettore 2d. E tutto funziona bene. Le particelle nel vettore vengono aggiornate. Ma con il secondo esempio il mio programma gira ma in qualche modo, indipendentemente dalla funzione doSpring, le particelle nel vettore 2D non vengono aggiornate.

+0

Come si dichiara "myParticles"? – coelhudo

+0

Ehi, un consiglio da http://www.drdobbs.com/cpp/184401863: "Non etichettare troppo i nomi, ma usa una convenzione di denominazione coerente: ci sono solo due cose da fare: a) non usare mai" nomi subdoli , "quelli che iniziano con un carattere di sottolineatura o che contengono un doppio trattino basso"; Words of Herb Sutter and Andrei Alexandrescu – coelhudo

risposta

0

Se ho capito bene, vuoi creare un array 2D di particelle usando std::vector?

Se così è possibile dichiararlo come: std::vector<std::vector<Particle> >. È quindi possibile utilizzare anche la nomenclatura [][] per accedere agli elementi. (Pericolo Will Robinson! Nessun confine controllo durante l'utilizzo di questo operatore)

Tuttavia, se questo array 2D conterrà per lo più zeri allora potrebbe essere ok per utilizzare un map con gli indici come chiavi.

+0

Giudicando dal suo codice ('.at (i) .at (j)'), sta già usando un vettore di vettori. –

+0

A giudicare dagli esempi precedenti, questo sembra esattamente quello che sta già cercando di fare (la parte "at (...). (...)"). – rjnilsson

1

Penso che this series da C++ FAQ Lite dovrebbe aiutare.

Si prega di non essere confuso da "operatore sovraccarico" intestazione.Dovresti assolutamente leggere 13.10, 13.11 e 13.12 da lì.

5

Quello che state facendo sembra ok - il codice seguente crea un vettore "2D" e mostra come l'.at() a() costrutto ti dà un punto di riferimento:

#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 dei più. problemi comuni che prendono riferimenti/puntatori agli elementi all'interno dei vettori è la riallocazione. Se si preme push_back, ad esempio, è possibile che il vettore superi la sua capacità, allocare un nuovo blocco di memoria, copiare tutto, quindi liberare il vecchio blocco. Se hai preso dei riferimenti o dei puntatori agli elementi all'interno del vettore, questi puntano ancora al vecchio blocco, ora alla memoria morta, ed è un bug serio!

Quindi immagino che il tuo effetto particellare continui ad aggiungere nuove particelle al vettore delle particelle, che a un certo punto provoca il riallineamento del vettore quando supera la capacità. I puntatori memorizzati dalla classe Spring non vengono tuttavia aggiornati, quindi puntare alla memoria morta e non avere alcun effetto sulla particella reale, che è stata spostata da un'altra parte dal vettore.

Non prendere un riferimento o un puntatore a un elemento all'interno di un vettore. Usa un vettore di puntatori, una lista o un altro contenitore che non si muoverà attorno agli indirizzi di memoria degli elementi reali. Se necessario, utilizzare gli iteratori per gli elementi all'interno di un vettore. Nelle build di debug, supponendo che tu abbia una implementazione STL controllata, riceverai un avviso di debug se accedi all'elemento attraverso l'iteratore dopo che il vettore si rialloca.

+1

Ma non causerebbe i puntatori nulli che causerebbero l'arresto anomalo dell'applicazione? Poiché la mia applicazione non si arresta, gli elementi semplicemente non vengono aggiornati. Tuttavia, questa è un'ottima risposta, non ho pensato alla riallocazione. – hrst

+0

No, niente viene impostato su un puntatore nullo: il vettore non conosce i puntatori nella classe Spring, quindi non fa mai alcun tentativo di cambiarli. I puntatori * non sono * modificati o nulli, puntano solo a una posizione di memoria morta. Poiché la memoria è probabilmente da qualche parte all'interno del tuo processo, sono consentite letture e scritture, nonostante tu stia probabilmente corrompendo la memoria dell'applicazione. – AshleysBrain