2009-05-03 17 views
5

Mi chiedo solo, a causa di un problema che sto incontrando, è possibile creare un vettore di puntatori? E se sì, come? In particolare per quanto riguarda utilizzando iteratori e .begin() con esso, vale a dire: Come faccio a girare questo vettore in un vettore di puntatori:È possibile creare un vettore di puntatori?

class c 
{ 
    void virtual func(); 
}; 

class sc:public c 
{ 
    void func(){cout<<"using func";} 
}; 

sc cobj; 

vector<c>cvect 
cvect.push_back(cobj); 
vector<c>::iterator citer 

for(citer=cvect.begin();citer<cvect.end();citer++) 
{ 
    citer->func(); 
} 

risposta

7

vector <c> cvect non è un vettore di puntatori. È un vettore di oggetti di tipo c. Vuoi vector <c*> cvect. e probabilmente la si desidera:

cvect.push_back(new c); 

E poi, dato un iteratore, si desidera qualcosa di simile:

(*it)->func(); 

Certo, è abbastanza probabile che non volevi un vettore di puntatori nel primo posto ...

+1

func() è una funzione virtuale, quindi suppongo che sia necessario il vettore di puntatori. – Naveen

+0

ah sì - buon punto –

+1

E se si spinge push_back(), probabilmente si vuole evitare di perdere il nuovo c. – bk1e

2

Hai creato vector<c*> per un vettore di puntatori. Quindi utilizzare new per allocare la memoria per gli oggetti c e inserirli nel vettore. Inoltre, non dimenticare che devi chiamare tu stesso delete e vector.clear() non rilascerà la memoria allocata per gli oggetti c. Devi memorizzare c come vettore di puntatori qui, altrimenti la chiamata alla funzione virtuale non funzionerà.

2

Sì, certo.

// TestCPP.cpp : Defines the entry point for the console application. 
// 

#include "stdafx.h" 
#include <iostream> 
#include <vector> 


using namespace std; 

class c 
{ 
public: 
    void virtual func() = 0; 
}; 

class sc:public c 
{ 
public: 
    void func(){cout<<"using func";} 
}; 

int _tmain(int argc, _TCHAR* argv[]) 
{ 
    sc cobj; 

    vector<c*> cvect; 
    cvect.push_back(&cobj); 
    vector<c*>::iterator citer; 

    for(citer=cvect.begin();citer<cvect.end();citer++) 
    { 
     (*citer)->func(); 
    } 

    return 0; 
} 

Si prega di notare la dichiarazione di vector<c*> cvect e l'uso di cvect.push_back(&cobj).

Dal codice fornito, si sta utilizzando iteratore in modo errato. Per accedere al membro che un iteratore sta puntando devi usare *citer invece di citer da solo.

16

Sicuro.

vector<c*> cvect; 
cvect.push_back(new sc); 
vector<c*>::iterator citer; 
for(citer=cvect.begin(); citer != cvect.end(); citer++) { 
    (*citer)->func(); 
} 

cose da tenere a mente:

Avrai bisogno di pulitura dopo la vostra auto, se si utilizza in modo dinamico la memoria allocata come ho fatto nel mio esempio

esempio:

for(...) { delete *i; } 

Questo può essere semplificato utilizzando un vettore di shared_ptr s (come boost::shared_ptr). Non tentare di utilizzare std::auto_ptr per questo, non funzionerà (non verrà nemmeno compilato).

Un'altra cosa da tenere a mente, è evitare di utilizzare < per confrontare gli iteratori nel ciclo quando possibile, funzionerà solo per gli iteratori che modellano un iteratore di accesso casuale, il che significa che non è possibile modificare il codice da utilizzare per esempio a std::list.

+0

+1, colpisci tutti gli obiettivi (di cui sono a conoscenza almeno ...) –

4

Sì, è possibile, ed è infatti necessario utilizzare i puntatori se si desidera che il vettore contenga oggetti da un'intera gerarchia di classi anziché da un singolo tipo. (Se non si utilizzano i puntatori, si verificherà il temuto problema di object slicing - tutti gli oggetti vengono convertiti automaticamente in un tipo di classe base, che non viene diagnosticato dal compilatore e quasi certamente non è ciò che si desidera.)

class c 
{ 
    void virtual func(); 
}; 

class sc:public c 
{ 
    void func(){cout<<"using func";} 
}; 

sc cobj; 

vector<c*> cvect;    // Note the type is "c*" 
cvect.push_back(&cobj);  // Note the "&" 
vector<c*>::iterator citer; 

for(citer=cvect.begin();citer != cvect.end();citer++) // Use "!=" not "<" 
{ 
    (*citer)->func(); 
} 

Si noti che con un vettore di puntatori, è necessario fare la propria gestione della memoria, in modo da essere molto attenti - se si prevede di utilizzare oggetti locali (come sopra), non devono cadere di portata prima che il contenitore faccia. Se si utilizzano puntatori su oggetti creati con new, sarà necessario eseguire manualmente delete prima che il contenitore venga distrutto. È assolutamente necessario prendere in considerazione l'utilizzo di indicatori intelligenti in questo caso, ad esempio smart_ptr fornito da Boost.

0

Prova Boost Pointer Container Library. Ha diversi vantaggi rispetto al normale vettore di puntatori, ad esempio:

my_container.push_back(0);   // throws bad_ptr 
ptr_vector<X> pvec; 
std::vector<X*> vec; 
(*vec.begin())->foo(); // call X::foo(), a bit clumsy 
pvec.begin()->foo();  // no indirection needed 
Problemi correlati