2011-09-09 7 views
6

Voglio leggere i dati di N byte da un flusso di file e aggiungerli a un vettore. Quindi diciamo che abbiamo unLeggere N byte dal file e aggiungerli a un std :: vector

basic_ifstream<uint8_t> myFileStream; 

e

vector<uint8_t> myBuffer; 

Attualmente sto facendo qualcosa di simile:

myBuffer.reserve(N); 
for (int i=0; i<N; ++i) 
{ 
    uint8_t tmpByte; 
    myFileStream.read(&tmpByte, 1); 
    myBuffer.push_back(tmpByte); 
} 

ma questo è estremamente lento.

Ora ho provato a consentire a myFileStream.read di copiare i dati direttamente nel vettore. Dal momento che un vettore memorizza i suoi elementi in un percorso di archiviazione contigua, ho pensato che una cosa del genere dovrebbe essere possibile:

uint8_t* ptr = &myBuffer.back(); // there is already some elements in the buffer (I know) 
ptr++; // first element after existing data 
myBuffer.resize(myBuffer.size() + N); 
myFileStream.read(ptr, N); 

Ma con questo ottengo un errore di runtime (danneggiamento di heap). Cosa c'è di sbagliato in questa soluzione? O c'è un modo migliore per farlo comunque?

risposta

12

Il tuo problema è che resize potrebbe richiedere di riallocare l'intero vettore e quindi invalidare il tuo precedente ptr. È necessario prendere il puntatore solo dopo resize.

std::size_t oldSize = myBuffer.size(); 
// resize first 
myBuffer.resize(oldSize + N); 
uint8_t* ptr = &myBuffer[oldSize]; // already first element after existing data 
myFileStream.read(ptr, N); 

noti che come bonus questa implementazione funziona anche se il vettore originale è vuota (per N != 0, ovviamente).

+0

ora funziona :) grazie per il vostro aiuto! –

+4

@Ajeet: 'reserve()' non cambia 'size()' del contenitore. Apprezzo la correttezza rispetto alle prestazioni. –

+0

Vero. Sarebbe utile solo se stava usando push_back(). Cancellare il mio commento Grazie @R. Martinho –