Вообще говоря, наихудший сценарий будет в неоптимизированной отладочной сборке, где memcpy
не является встроенным и может выполнять дополнительные проверки здравого смысла / утверждения, составляющие небольшое количество дополнительных инструкций по сравнению с циклом for.
Однако memcpy
обычно хорошо реализован для использования таких вещей, как встроенные функции и т. Д., Но это будет зависеть от целевой архитектуры и компилятора. Маловероятно, что memcpy
когда-либо будет хуже, чем реализация цикла for.
Люди часто путаются в том, что размер memcpy в байтах, и пишут такие вещи:
// 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));
Здесь вы можете защитить себя, используя языковые функции, которые позволяют вам в некоторой степени задуматься, а именно: делать вещи с точки зрения самих данных, а не того, что вы знаете о данных, потому что в общей функции вы обычно не ничего не знаю о данных:
void foo (int* nums, size_t numNums)
{
memcpy(myGlobalArray, nums, numNums * sizeof(*nums));
}
Обратите внимание, что вы не хотите использовать "&" перед "myGlobalArray", потому что массивы автоматически распадаются на указатели; вы на самом деле копировали «nums» по адресу в памяти, где хранился указатель на myGlobalArray [0].
( Редактировать заметку: я бы опечатал int[] nums
, когда я имею в виду не int nums[]
, но я решил, что добавление C-указатель-указателя массива хаоса никому не помогло, так что теперь это int *nums
:) )
Использование memcpy
на объектах может быть опасным, рассмотрим:
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));
Это НЕПРАВИЛЬНЫЙ способ копирования объектов, которые не являются POD (обычные старые данные). И f1, и f2 теперь имеют std :: string, которая считает, что ей принадлежит «hello». Один из них потерпит крах, когда разрушится, и они оба думают, что имеют один и тот же вектор целых чисел, который содержит 42.
Лучшая практика для программистов на C ++ - использовать std::copy
:
std::copy(nums, nums + numNums, myGlobalArray);
Примечание по Реми Лебо или начиная с C ++ 11
std::copy_n(nums, numNums, myGlobalArray);
Это может принимать решения во время компиляции о том, что делать, включая использование memcpy
или memmove
и, возможно, использование инструкций SSE / vector, если это возможно. Еще одним преимуществом является то, что если вы напишите это:
struct Foo {
int m_i;
};
Foo f1[10], f2[10];
memcpy(&f1, &f2, sizeof(f1));
и позже измените Foo на std::string
, ваш код сломается. Если вы вместо этого напишите:
struct Foo {
int m_i;
};
enum { NumFoos = 10 };
Foo f1[NumFoos], f2[NumFoos];
std::copy(f2, f2 + numFoos, f1);
компилятор переключит ваш код для правильной работы без какой-либо дополнительной работы для вас, и ваш код станет немного более читабельным.