0

I have seen the difference pointed in the accepted answer in What is the difference between memmove and memcpy? and it said memmove might be very slightly slower than memcpy.

We can implement an alternative for memmove by doing as follows: allocate a temporary buffer, then memcpy twice (src -> tmp, tmp -> dest). My question is: which way is faster, memmove or the alternative?

xaxxon
  • 19,189
  • 5
  • 50
  • 80
duong_dajgja
  • 4,196
  • 1
  • 38
  • 65
  • It depends on the target machine and the implementation. –  Jul 07 '17 at 08:41
  • 5
    Copy data is slow. Copy data *twice* will be slower. That `memmove` *might* be slower than `memcpy` is because it is able to handle overlapping memory, but `memmove` still only copies the data *once*. – Some programmer dude Jul 07 '17 at 08:41
  • 1
    profile it on the platform you're interested in the timings for. However, the chances of you writing a better memmove than memmove seems unlikely. – xaxxon Jul 07 '17 at 08:43
  • The standard `memmove` of your platform is most likely already highly optimized, so just use `memmove` if source and destination may overlap and don't bother. If you are sure that source and destination will never overlap, then just use `memcpy`. – Jabberwocky Jul 07 '17 at 08:46

2 Answers2

6

From http://en.cppreference.com/w/cpp/string/byte/memmove

Despite being specified "as if" a temporary buffer is used, actual implementations of this function do not incur the overhead of double copying or extra memory. For small count, it may load up and write out registers; for larger blocks, a common approach (glibc and bsd libc) is to copy bytes forwards from the beginning of the buffer if the destination starts before the source, and backwards from the end otherwise, with a fall back to std::memcpy when there is no overlap at all.

Therefore the overhead in all likelihood is a couple of conditional branches. Hardly worth worrying about for large blocks.

However, it is worth remembering that std::memcpy is a 'magic' function, being the only legal way to cast between two dissimilar types.

In c++, this is illegal (undefined behaviour):

union {
  float a;
  int b;
} u;

u.a = 10.0;
int x = u.b;

This is legal:

float a = 10.0;
int b;
std::memcpy(std::addressof(b), std::addressof(a), size(b));

and does what you'd expect the union to do if you were a C programmer.

Stargateur
  • 24,473
  • 8
  • 65
  • 91
Richard Hodges
  • 68,278
  • 7
  • 90
  • 142
2

std::memmove "may be very slightly slower than std::memcpy" (emphasis added) because it has to first check whether the source and target ranges overlap. Internally, that's just a couple of pointer comparisons; having done that, if there's no overlap or the target starts below the source, it calls std::memcpy; otherwise, it calls a variant of std::memcpy that copies from the end toward the beginning.

In short, there only difference is that initial comparison; once that's done, it's just like std::memcpy. No need for that extra buffer and copying everything twice.

Pete Becker
  • 74,985
  • 8
  • 76
  • 165