Under what conditions is it safe to use std::memcp

2020-07-22 16:23发布

问题:

Under what set of conditions is it safe to use std::memcpy to copy from one object to another?

For example, what conditions must T, src and dest satisfy for the following to be safe:

template <typename T>
void copy_bytewise(T& dest, const T& src) {
  std::memcpy(&dest, &src, sizeof(T));
}

The only thing we can assume about src and dest is that they don't overlap1. In particular either of src or dest may be a reference to a member or base class.

I am interested in answers which refer to the standard, but if this diverges from common practice (e.g., the de-facto C++ ABI from Itanium) I'd also like to know.

Note that T satisfying the TriviallyCopyable (TC) concept is not sufficient, as this example shows. base is TC yet not memcpy-safe (due to re-use of padding for members of a derived class).

I am especially interested if there is any condition on T alone that is sufficient (and not necessarily necessary), without requiring conditions on src and dest (that cannot, in general, be statically determined).


1 Specifically, my assumption is that if they do overlap, they are still safe to copy under the same conditions on T as for std::memcpy, but using std::memmove instead. If assumption is incorrect, it could be part of an answer.

回答1:

From [basic.types]/3:

For any trivially copyable type T, if two pointers to T point to distinct T objects obj1 and obj2, where neither obj1 nor obj2 is a base-class subobject, if the underlying bytes ([intro.memory]) making up obj1 are copied into obj2, obj2 shall subsequently hold the same value as obj1.

In short:

what conditions must T satisfy for the following to be safe

T must be trivially copyable; that's the only condition that T must satisfy. The other requirement is not a restriction on T, but a restriction on the nature of the objects potentially being copied. Which means it's not something you can statically determine.