In generale, lo scenario peggiore si trova in una build di debug non ottimizzata in cui memcpy
non è in linea e può eseguire ulteriori controlli di integrità/asserzione per un numero limitato di istruzioni aggiuntive rispetto a un ciclo for.
Tuttavia, memcpy
è generalmente ben implementato per sfruttare elementi intrinseci, ecc., Ma questo varierà con l'architettura di destinazione e il compilatore. È improbabile che memcpy
sarà sempre peggio di un'implementazione for-loop.
La gente spesso inciampare il fatto che le dimensioni memcpy in byte, e scrivono cose come queste:
// wrong unless we're copying bytes.
memcpy(myGlobalArray, nums, numNums);
// wrong if an int isn't 4 bytes or the type of nums changed.
memcpy(myGlobalArray, nums, numNums);
// wrong if nums is no-longer an int array.
memcpy(myGlobalArray, nums, numNums * sizeof(int));
È possibile proteggersi qui utilizzando funzionalità del linguaggio che consentono di fare un certo grado di riflessione, cioè : fare le cose in termini di dati stessi, piuttosto che quello che sai sui dati, perché in una funzione generica in genere non si sa nulla circa i dati:
void foo (int[] nums, size_t numNums)
{
memcpy(myGlobalArray, nums, numNums * sizeof(*nums));
}
Nota che non si desidera che il " & "davanti a" myGlob alArray "perché gli array decadono automaticamente ai puntatori; in effetti stavi copiando "numeri" all'indirizzo in memoria dove si trovava il puntatore a myGlobalArray [0].
Uso memcpy
su oggetti può essere pericoloso, considerare:
struct Foo {
std::string m_string;
std::vector<int> m_vec;
};
Foo f1;
Foo f2;
f2.m_string = "hello";
f2.m_vec.push_back(42);
memcpy(&f1, &f2, sizeof(f2));
questo è il modo sbagliato per copiare gli oggetti che non sono POD (dati vecchi pianura). Sia f1 che f2 ora hanno una stringa std :: che pensa che possieda "ciao". Uno di loro sta per bloccarsi quando Destruct, ed entrambi pensano che possiedono lo stesso vettore di interi che contiene 42.
La pratica migliore per C++ i programmatori è quello di utilizzare std::copy
:
std::copy(nums, nums + numNums, myGlobalArray);
Questo può prendere decisioni sulla durata della compilazione su cosa fare, incluso l'utilizzo di memcpy
o memmove
e, se possibile, utilizzare potenzialmente le istruzioni SSE/vettoriali. Un altro vantaggio è che se si scrive questo:
struct Foo {
int m_i;
};
Foo f1[10], f2[10];
memcpy(&f1, &f2, sizeof(f1));
e più tardi sul cambiamento Foo per includere un std::string
, il codice si romperà. Se invece scrive:
struct Foo {
int m_i;
};
enum { NumFoos = 10 };
Foo f1[NumFoos], f2[NumFoos];
std::copy(f2, f2 + numFoos, f1);
il compilatore passerà il codice per fare la cosa giusta, senza alcun lavoro supplementare per voi, e il codice è un po 'più leggibile.
Hai provato a compilare i tuoi esempi? –
Possibile duplicato di [Perché memcpy() e memmove() sono più veloci degli incrementi del puntatore?] (Http://stackoverflow.com/questions/7776085/why-is-memcpy-and-memmove-faster-than-pointer-increments) Sebbene questo non accennino più velocemente, entrambi i frammenti sono funzionalmente corretti, quindi si tratterà di questo. –