Scaricare la presentazione
La presentazione è in caricamento. Aspetta per favore
1
Vettori dinamici Definiremo la classe vector.
La classe rappresenta un vettore dimensionabile dinamicamente. Ha un parametro template che definisce il tipo di dato contenuto nel vettore. L’implementazione proposta e’ volutamente rozza. Vedremo come la stessa classe sia implementanta nella Standard Template Library. 21 novembre 2018 Claudio Rocchini IGMI
2
Vector: implementazione
La classe vector e’ definita da tre valori: Size: la dimensione corrente del vettore, ovvero il numero dei suoi elementi. Memo: il numero di elementi allocati realmente, che deve essere maggiore o uguale a size. Data: la memoria allocata vera e propria. La classe e’ parametrizzata secondo il tipo T, che rappresenta il tipo degli elementi contenuti nel vettore. 21 novembre 2018 Claudio Rocchini IGMI
3
Vector: Intestazione template<class T> // Parametro template
class vector { private: // Dati privati T * data; // Memoria allocata int size; // Dimensione corrente int memo; // Dim. memoria allocata }; Data contiene il vettore vero e proprio, size memorizza la dimensione reale del vettore, memo la memoria allocata (>= size). 21 novembre 2018 Claudio Rocchini IGMI
4
Vector: costruttore 1 inline vector() {
data = 0; // Inizializzazione variabili size = 0; memo = 0; } Il costruttore di default definisce un vettore con zero elementi e zero posizioni allocate. 21 novembre 2018 Claudio Rocchini IGMI
5
Vector: costruttore 2 Inline vector( int s ) { assert(s>0);
data = new T[s]; // Allocazione memoria assert(data!=0); size = s; // Definizione di size memo = s; // Definizione di memo } Costruttore con allocazione iniziale della dimensione; lo spazio allocato coincide con la dimensione attuale. 21 novembre 2018 Claudio Rocchini IGMI
6
Vector: distruttore inline void clear() {
if(data) delete[] data; // Disallocazione data = 0; size = memo = 0; } inline ~vector() clear(); E’ importante dichiarare il distruttore della classe; il distruttore si occupa di disallocare la memoria dei dati. 21 novembre 2018 Claudio Rocchini IGMI
7
Vector: accesso agli elementi
inline T & operator[] ( const int i ) { assert(i>=0 && i<size); return data[i]; } inline const T & operator[] ( int i ) const Operatore[]: accesso agli elementi del vettore, come al solito di definisce anche la versione costante. 21 novembre 2018 Claudio Rocchini IGMI
8
Vector: espansione inline void reserve( int m ) { if(m>memo)
T * tmp = new T[m]; // Alloc. nuovo vettore for(int i=0;i<size;++i) // Copia dati tmp[i] = data[i]; if(data) delete[] data;// Disalloc. memoria data = tmp; memo = s; } } Questo metodo ridimensiona la memoria allocata senza modificare il vettore. 21 novembre 2018 Claudio Rocchini IGMI
9
Vector: ridimensionamento
inline void resize( int s ) { reserve(s); size = s; // Assegnamento dimensione } Questo metodo espande (o riduce) il numero di elementi del vettore, la chiamata a reserve assicura che la memoria allocata sia sufficiente. 21 novembre 2018 Claudio Rocchini IGMI
10
Vector: aggiunta di 1 elemento
inline void push_back( const T & e ) { reserve(size+1); data[size++] = e; } Il metodo aggiunge un elemento in coda al vettore; tuttavia, in caso di aggiunta di molti elementi, l’implementazione risulta eccessivamente inefficiente: si esegua una riallocazione (con copiatura dei dati) per ogni elemento aggiunto. 21 novembre 2018 Claudio Rocchini IGMI
11
Vector: aggiunta efficiente
inline void push_back( const T & e ) { if(size==memo) // Necessaria riallocazione if(memo==0) reserve(256); else reserve(memo*2); } data[size++] = e; Con questa implementazione, per ogni n inserzioni nel vettore, si eseguono al piu’ log(n) espansioni (perche?). 21 novembre 2018 Claudio Rocchini IGMI
12
Vector: controlli inline bool is_empty() const { return size==0; }
inline int size() const return size; Il metodo is_empty constrolla se il vettore e’ vuoto. Il metodo size ritorna il numero di elementi del vettore. 21 novembre 2018 Claudio Rocchini IGMI
13
Vector: assegnamento errato
La funzione di assegnamento di default, copia i dati propri della classe nel seguente modo: Inline vector & operator= ( const vector & v ) { data = v.data; size = v.size; memo = v.memo; return *this; } Il funzionamento risulta errato. 21 novembre 2018 Claudio Rocchini IGMI
14
Vector: assegnamento errato(2)
V1.data V2.data copia 21 novembre 2018 Claudio Rocchini IGMI
15
Vector: assegnamento corretto
inline vector & operator= ( const vector & v ) { if(v.size>memo) // Memoria insuff. if(data) delete[] data; // Riallocazione memo = v.size; data = new T[memo]; } for(int i=0;i<v.size;++i) // Copia elementi data[i] = v.data[i]; size = v.size; // Aggiorn. dimensione 21 novembre 2018 Claudio Rocchini IGMI
16
Vector: esempio di utilizzo
… vector<char> v(10); // vettore di 10 char V[3] = ‘x’; // Assegnamento elemento v.push_back(‘y’); // Aggiunta in coda cout << v.size(); // stampa: 11 vector<char> w; // Dichiarazione w = v; // assegnamento vettori Vector<char> k[10]; // ATTENZIONE: si e’ // dichiarato 10 vettori 21 novembre 2018 Claudio Rocchini IGMI
17
Vector: introduzione agli iteratori
char v[100]; for(int i=0;i<100;++i) // (1)Iterazione con indice operazione(v[i]); for(char* j=v;j<v+100;++j) // (2)Iteraz. con puntatore operazione(*j); L’iterazione degli elementi di un vettore si effettua di solito tramite indici (caso 1) o tramite puntatori (caso 2). Di solito il secondo metodo e’ piu’ efficiente, non richiede infatti il calcolo dell’indirizzo dell’elemento. Come si procede nel caso della classe vector? 21 novembre 2018 Claudio Rocchini IGMI
18
Vector: iteratori typedef T * iterator; inline iterator begin() { return data; } inline iterator end() return data+size; Definiamo il tipo di dato iterator, che e’ un estensione del puntatore. Definiamo inoltre i metodi begin e end che ritornano gli iteratori all’inizio e alla fine del vettore. 21 novembre 2018 Claudio Rocchini IGMI
19
Vector: utilizzo degli iteratori
vector<char> v(100); vector<char>::iterator i; for(i=v.begin();v!=v.end();++i) operazione(*i); L’iteratore si utilizza in modo del tutto analogo al puntatore. 21 novembre 2018 Claudio Rocchini IGMI
20
Vector: un’altra implementazione
Abbiamo visto un’implementazione veramente rozza della classe vector. In realta’ la classe vector e’ gia’ implementata in maniera piu’ efficiente nella libreria standard del C++. Tale implementazione ha le stesse funzionalita’ da noi implementate piu’ altre aggiuntive. La classe vector della libreria standard ha un secondo parametro template, che specifica la politica di riallocazione della memoria. 21 novembre 2018 Claudio Rocchini IGMI
21
Esercizi Per quanto riguarda la classe vector:
Definire i metodi front() e back() che ritornano il riferimento al primo e all’ultimo elemento del vettore. Definire il metodo pop_back() che elimina l’ultimo elemento del vettore. Definire il metodo erase( iterator p ) che elimina dal vettore l’elemento indicato da p e ricompatta gli altri valori (*). (*) esercizio piu’ impegnativo. 21 novembre 2018 Claudio Rocchini IGMI
Presentazioni simili
© 2024 SlidePlayer.it Inc.
All rights reserved.