PDA

View Full Version : [C++] Reimplementazione vector e uso iterator.


panda84
30-11-2009, 15:51
Ciao a tutti!

Per motivi vari (vecchio sistema operativo embebbed che gira dentro un vecchio e malfunzionante simulatore ARM di cui non posso fare a meno) sto reimplementando una piccola parte della classe vector in modo da poter utilizzare codice di terze parti che usa la succitata classe senza doverne modificare tutto il codice.

Sono riuscito a implementare tutti i metodi di base che mi servono dalla classe vector e sembra funzionare tutto senza problemi. Ora ho un ultimo scoglio da superare; ho letto qui:
http://www.cplusplus.com/reference/std/iterator/
che il puntatore è una forma di iteratore. Per semplicità, visto che non sono pratico di iteratori, ho utilizzato temporaneamente dei puntatori. Ad esempio invece di definire:
iterator begin ();
come nelle STL:
http://www.cplusplus.com/reference/stl/vector/begin/
ho utilizzato:
T* begin();

Ora però, mentre con l'implementazione STL di vector i cicli si fanno così:
for (vector<int>::iterator it = myobject.begin(); it != myobject.end(); it++)
io devo farli così.
for (int* it = myobject.begin(); it != myobject.end(); it++)
Cosa devo cambiare nella mia implementazione per usare la sintassi originale? Ovvero, non capisco cosa devo fare "internamente" alla mia versione di vector per ottenere "esternamente" la sintassi:
vector<int>::iterator

Anche in questo esempio:
http://www.cplusplus.com/reference/std/iterator/iterator/
ottengono:
myiterator it=beginning

Scusate, ma credo di avere ancora qualche difficoltà con le classi template...

Grazie a chiunque proverà ad aiutarmi! :)
Diego


P.S.: Se volete vedere la mia "barbara" implementazione di vector posso metterla su pastebin senza problema.

cionci
30-11-2009, 16:40
Ti definisci una classe iterator pubblica all'interno di vector. Al suo interno contiene un puntatore al tipo del vector. Ti devi ridefinire l'operatore ++ e l'operatore *.

Altra alternativa, magari stupida e che non ti consente tutto il controllo del normale iterator è

typedef T* iterator;

all'interno di vector.

cionci
30-11-2009, 16:40
P.S.: Se volete vedere la mia "barbara" implementazione di vector posso metterla su pastebin senza problema.
Vai ;)

panda84
30-11-2009, 17:15
Ti definisci una classe iterator pubblica all'interno di vector. Al suo interno contiene un puntatore al tipo del vector. Ti devi ridefinire l'operatore ++ e l'operatore *.

Altra alternativa, magari stupida e che non ti consente tutto il controllo del normale iterator è

typedef T* iterator;

all'interno di vector.

Ottimo, grazie mille dei consigli! Domani faccio sapere l'esito degli esperimenti.


Ecco l'implementazione... se vedete qualche castrone, è normale: sono i miei primi esperimenti con C++! Se però me li fate notare vi ringrazio. :)
http://pastebin.com/m2b276848
Per ora mi basta che funzioni, poi gli accessori li aggiungo dopo (tipo l'array si allunga ma non si accorcia). È molto limitato, ma per quello che andrà a fare va più che benone...

cionci
30-11-2009, 17:34
Ho visto che ogni volta fai una copia. Non è secondo me una buona politica. Ovviamente è l'unica utilizzando il typdef per l'iterator, ma se ti crei una classe per l'iterator allora ti conviene fare un'allocazione a blocchi.
Per simulare la continuità dell'array basta fare un'operazione del genere:
data[i / BLOCK_SIZE][i % BLOCK_SIZE]

Ovviamente in data[i / BLOCK_SIZE] ci sarà l'indirizzo del blocco allocato in memoria.
Quando allochi un nuovo blocco dovrai solo allungare il vettore data, copiandone i valori (in teoria puoi fare anche questo a blocchi di M elementi, così fai una copia solo ogni N * BLOCK_SIZE elementi inseriti nel vettore).

panda84
30-11-2009, 22:11
Ho visto che ogni volta fai una copia. Non è secondo me una buona politica. Ovviamente è l'unica utilizzando il typdef per l'iterator, ma se ti crei una classe per l'iterator allora ti conviene fare un'allocazione a blocchi.
Per simulare la continuità dell'array basta fare un'operazione del genere:
data[i / BLOCK_SIZE][i % BLOCK_SIZE]

Ovviamente in data[i / BLOCK_SIZE] ci sarà l'indirizzo del blocco allocato in memoria.
Quando allochi un nuovo blocco dovrai solo allungare il vettore data, copiandone i valori (in teoria puoi fare anche questo a blocchi di M elementi, così fai una copia solo ogni N * BLOCK_SIZE elementi inseriti nel vettore).

Ma ne sai a pacchi! :D
Ti sei guadagnato una citazione nei rigraziamenti della mia tesi! ;)

Nel frattempo ho scoperto un altro errore da niubbo: non si possono separare i template in .h e .cpp. Cioè compilare compila, ma al momento di linkare sono inni che si elevano al signore... :doh:

Domani a mente fresca sistemerò un po' il tutto, intanto grazie ancora.

cionci
30-11-2009, 23:07
Di niente ;)