Domanda

Ho un array di valori che viene passato alla mia funzione da una parte diversa del programma che devo memorizzare per l'elaborazione successiva. Dato che non so quante volte la mia funzione verrà chiamata prima che sia il momento di elaborare i dati, ho bisogno di una struttura di archiviazione dinamica, quindi ho scelto un std :: vector . Non voglio fare il ciclo standard per push_back tutti i valori singolarmente, sarebbe bello se potessi semplicemente copiarlo usando qualcosa di simile a memcpy .

È stato utile?

Soluzione

Se puoi costruire il vettore dopo aver ottenuto l'array e le dimensioni dell'array, puoi semplicemente dire:

std::vector<ValueType> vec(a, a + n);

... supponendo che a sia l'array e n sia il numero di elementi che contiene. Altrimenti, std :: copy () w / resize () farà il trucco.

Starei alla larga da memcpy () a meno che tu non sia sicuro che i valori siano tipi di dati semplici (POD).

Inoltre, vale la pena notare che nessuno di questi evita davvero il ciclo for - è solo una questione se devi vederlo nel tuo codice o meno. O (n) le prestazioni di runtime sono inevitabili per la copia dei valori.

Infine, nota che gli array in stile C sono contenitori perfettamente validi per la maggior parte degli algoritmi STL: il puntatore non elaborato è equivalente a begin () e ( ptr + n ) equivale a end () .

Altri suggerimenti

Ci sono state molte risposte qui e quasi tutte faranno il loro lavoro.

Comunque ci sono alcuni consigli fuorvianti!

Ecco le opzioni:

vector<int> dataVec;

int dataArray[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
unsigned dataArraySize = sizeof(dataArray) / sizeof(int);

// Method 1: Copy the array to the vector using back_inserter.
{
    copy(&dataArray[0], &dataArray[dataArraySize], back_inserter(dataVec));
}

// Method 2: Same as 1 but pre-extend the vector by the size of the array using reserve
{
    dataVec.reserve(dataVec.size() + dataArraySize);
    copy(&dataArray[0], &dataArray[dataArraySize], back_inserter(dataVec));
}

// Method 3: Memcpy
{
    dataVec.resize(dataVec.size() + dataArraySize);
    memcpy(&dataVec[dataVec.size() - dataArraySize], &dataArray[0], dataArraySize * sizeof(int));
}

// Method 4: vector::insert
{
    dataVec.insert(dataVec.end(), &dataArray[0], &dataArray[dataArraySize]);
}

// Method 5: vector + vector
{
    vector<int> dataVec2(&dataArray[0], &dataArray[dataArraySize]);
    dataVec.insert(dataVec.end(), dataVec2.begin(), dataVec2.end());
}

Per farla breve Un metodo 4, usando vector :: insert, è il migliore per lo scenario di bsruth.

Ecco alcuni dettagli cruenti:

Metodo 1 è probabilmente il più facile da capire. Basta copiare ogni elemento dall'array e spingerlo nella parte posteriore del vettore. Ahimè, è lento. Poiché esiste un ciclo (implicito con la funzione copia), ogni elemento deve essere trattato singolarmente; non è possibile apportare miglioramenti delle prestazioni in base al fatto che sappiamo che l'array e i vettori sono blocchi contigui.

Metodo 2 è un miglioramento delle prestazioni suggerito rispetto al Metodo 1; basta prenotare in anticipo la dimensione dell'array prima di aggiungerlo. Per array di grandi dimensioni questo potrebbe aiutare. Tuttavia, il miglior consiglio qui non è mai usare la riserva a meno che la profilazione suggerisca che potresti essere in grado di ottenere un miglioramento (o devi assicurarti che i tuoi iteratori non vengano invalidati). Bjarne è d'accordo . Per inciso, ho scoperto che questo metodo ha funzionato il più lento la maggior parte delle volte, anche se faccio fatica a spiegare in modo completo perché era regolarmente significativamente più lento del metodo 1 ...

Metodo 3 è la soluzione della vecchia scuola - lancia un po 'di C al problema! Funziona bene e velocemente per i tipi POD. In questo caso è necessario chiamare il ridimensionamento poiché memcpy funziona al di fuori dei limiti del vettore e non c'è modo di dire a un vettore che le sue dimensioni sono cambiate. Oltre ad essere una brutta soluzione (copia byte!) Ricorda che questo può essere usato solo per i tipi POD . Non userei mai questa soluzione.

Metodo 4 è il modo migliore di procedere. Il suo significato è chiaro, è (di solito) il più veloce e funziona per qualsiasi oggetto. Non vi è alcun aspetto negativo nell'utilizzare questo metodo per questa applicazione.

Metodo 5 è una modifica del Metodo 4: copia l'array in un vettore e poi aggiungilo. Buona opzione - generalmente veloce e chiara.

Infine, sei consapevole che puoi usare i vettori al posto degli array, giusto? Anche quando una funzione prevede array di tipo c è possibile utilizzare i vettori:

vector<char> v(50); // Ensure there's enough space
strcpy(&v[0], "prefer vectors to c arrays");

Spero che aiuti qualcuno là fuori!

Se tutto ciò che stai facendo è sostituire i dati esistenti, puoi farlo

std::vector<int> data; // evil global :)

void CopyData(int *newData, size_t count)
{
   data.assign(newData, newData + count);
}

std :: copy è quello che stai cercando.

Poiché posso solo modificare la mia risposta, ho intenzione di creare una risposta composita dalle altre risposte alla mia domanda. Grazie a tutti coloro che hanno risposto.

Utilizzando std :: copy , questo continua ancora in background, ma non è necessario digitare il codice.

int foo(int* data, int size)
{
   static std::vector<int> my_data; //normally a class variable
   std::copy(data, data + size, std::back_inserter(my_data));
   return 0;
}

Utilizzo dei normali memcpy . Questo è probabilmente meglio utilizzato per tipi di dati di base (cioè int) ma non per array più complessi di strutture o classi.

vector<int> x(size);
memcpy(&x[0], source, size*sizeof(int));
int dataArray[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };//source

unsigned dataArraySize = sizeof(dataArray) / sizeof(int);

std::vector<int> myvector (dataArraySize );//target

std::copy ( myints, myints+dataArraySize , myvector.begin() );

//myvector now has 1,2,3,...10 :-)

evita il memcpy, dico. Nessun motivo per scherzare con le operazioni del puntatore a meno che non sia necessario. Inoltre, funzionerà solo per i tipi POD (come int) ma fallirebbe se hai a che fare con tipi che richiedono costruzione.

Oltre ai metodi presentati sopra, è necessario assicurarsi di utilizzare std :: Vector.reserve (), std :: Vector.resize () o di costruire il vettore in base alle dimensioni, per assicurarsi che il vettore abbia abbastanza elementi per contenere i tuoi dati. in caso contrario, danneggierai la memoria. Questo vale sia per std :: copy () che per memcpy ().

Questo è il motivo per usare vector.push_back (), non puoi scrivere oltre la fine del vettore.

Ancora un'altra risposta, dato che la persona ha detto "Non so quante volte la mia funzione verrà chiamata", potresti usare il metodo di inserimento vettoriale in questo modo per aggiungere matrici di valori alla fine del vettore:

vector<int> x;

void AddValues(int* values, size_t size)
{
   x.insert(x.end(), values, values+size);
}

Mi piace in questo modo perché l'implementazione del vettore dovrebbe essere in grado di ottimizzare per il modo migliore di inserire i valori in base al tipo di iteratore e al tipo stesso. Stai rispondendo in qualche modo all'implementazione di stl.

Se devi garantire la massima velocità e sai che il tuo tipo è un tipo POD, allora consiglierei il metodo di ridimensionamento nella risposta di Thomas:

vector<int> x;

void AddValues(int* values, size_t size)
{
   size_t old_size(x.size());
   x.resize(old_size + size, 0);
   memcpy(&x[old_size], values, size * sizeof(int));
}

Supponendo che tu sappia quanto sono grandi gli oggetti nel vettore:

std::vector<int> myArray;
myArray.resize (item_count, 0);
memcpy (&myArray.front(), source, item_count * sizeof(int));

http://www.cppreference.com/wiki/stl/vector/start

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top