Я видел разницу, указанную в принятом ответе в В чем разница между memmove и memcpy? и сказал memmove might be very slightly slower than memcpy
,
Мы можем реализовать альтернативу для memmove
сделав следующее: выделите временный буфер, затем memcpy
дважды (src -> tmp, tmp -> dest). Мой вопрос: какой путь быстрее, memmove
или альтернатива?
От http://en.cppreference.com/w/cpp/string/byte/memmove
Несмотря на то, что указано, что «как будто» используется временный буфер, фактические реализации этой функции не несут затрат на двойное копирование или дополнительную память. Для небольшого подсчета он может загружать и записывать регистры; для больших блоков общий подход (glibc и bsd libc) состоит в том, чтобы копировать байты вперед от начала буфера, если место назначения начинается перед источником, и назад от конца в противном случае, с возвратом к std :: memcpy, когда есть не перекрывается вообще.
Поэтому накладные расходы, по всей вероятности, представляют собой пару условных ветвей. Вряд ли стоит беспокоиться о больших блоках.
Однако стоит помнить, что std::memcpy
является «магической» функцией, являющейся единственным законным способом разыгрывания двух разных типов.
В c ++ это недопустимо (неопределенное поведение):
union {
float a;
int b;
} u;
u.a = 10.0;
int x = u.b;
Это законно:
float a = 10.0;
int b;
std::memcpy(std::addressof(b), std::addressof(a), size(b));
и делает то, что вы ожидаете от союза, если вы были программистом Си.
std::memmove
«может быть очень немного медленнее чем std::memcpy
«(выделение добавлено), потому что он должен сначала проверить, перекрываются ли диапазоны источника и цели. Внутренне, это всего лишь пара сравнений указателей; после этого, если нет перекрытия или цель начинается ниже источника, он вызывает std::memcpy
; в противном случае он вызывает вариант std::memcpy
это копирует от конца к началу.
Короче говоря, есть только разница в том, что первоначальное сравнение; как только это будет сделано, это так же, как std::memcpy
, Нет необходимости в этом дополнительном буфере и копировании всего дважды.
Memcpy, как правило, работает быстрее, поскольку не предполагает, что место назначения и источник могут перекрываться.
Итак, если вы попытаетесь использовать memcpy для копирования строки abcd
из местоположения X
в X+2
можно получить такой результат
X: A B C D
после memcpy
X+2 A B A A
в то время как memmove гарантирует, что ничего не потеряно, потому что он использует промежуточный буфер для хранения исходной строки.
С другой стороны, вы можете использовать классификатор restrict
для источника и получателя и тому подобное вы можете сказать memmove, что источник и получатель не перекрываются, и, как этот, memmove может выбрать другой более быстрый алгоритм, если вы используете этот классификатор.
Подробнее см. Вот.