Does the same trivially-copyable limitation that applies to `memcpy()` also apply to `std::copy()`?

271 views Asked by At

Cppreference states, regarding std::memcpy() (emphasis added):

If the objects are potentially-overlapping or not TriviallyCopyable, the behavior of memcpy is not specified and may be undefined.

So, I always check to ensure an object IS trivially-copyable before using memcpy(), like this:

#include <type_traits>

static_assert(std::is_trivially_copyable<T>::value, "Type T must "
    "be a trivially-copyable type in order to guarantee that `memcpy()` is safe "
    "to use on it.");
memcpy(&outputData, &data, sizeof(data));

std::copy(), however, doesn't seem to have this limitation: https://en.cppreference.com/w/cpp/algorithm/copy.

Does this limitation that the type must be trivially-copyable to not have undefined behavior NOT apply to std::copy()?

Also, I just realized in my "placement new" answer here, which made me wonder about this whole thing, I used just memcpy() instead of std::memcpy(), and I was not using namespace std;, so which function was called? Is memcpy() a different implementation from std::memcpy()?

2

There are 2 answers

0
Eugene On
  1. std::copy is a simple standard algorithm. Its general version just uses assignment in a loop, so it is applicable in the same cases as assignment. Library implementers will usually have a special implementation of std::copy through memcpy when it is safe to do so and is faster than assignment. Since memcpy is a legacy C function, it should almost never be used in C++ outside low-level libraries,.

  2. ::memcpy and std::memcpy is really the same thing, because it is coming from C standard library. Formally, you should use ::memcpy if you #include <string.h> and std::memcpy if you #include <cstring>, but in practice ::memcpy is always available.

1
Nicol Bolas On

memcpy is a function that copies bytes. std::copy copies objects. In some cases, copying the bytes of an object can copy the object.

But these are not the same thing. std::copy sees bytewise copying of memory as a potential optimization under certain circumstances in pursuit of its goal: copying objects. It's an implementation detail. For memcpy, bytewise copying is what it does; that bytewise copying can sometimes copy an object is maybe a side benefit.

It should also be noted that std::copy operates on generic iterators. It can "copy" into a ofstream via a proper ostream_iterator, or it can copy from an ifstream via an istream_iterator. std::copy is not fussy about the source or destination. By contrast, memcpy requires that you're copying from and to a contiguous sequence of bytes (and that these sequences are disjoint).