При каких условиях безопасно использовать std::memcpy для копирования между объектами?
При каких условиях безопасно использовать std::memcpy
копировать с одного объекта на другой?
Например, какие условия должны T
, src
а также dest
удовлетворить следующие требования для безопасности:
template <typename T>
void copy_bytewise(T& dest, const T& src) {
std::memcpy(&dest, &src, sizeof(T));
}
Единственное, что мы можем предположить о src
а также dest
в том, что они не перекрываются1. В частности, любой изsrc
или dest
может быть ссылкой на член или базовый класс.
Меня интересуют ответы, относящиеся к стандарту, но если это отличается от общепринятой практики (например, де-факто C++ ABI от Itanium), я также хотел бы знать.
Обратите внимание, что T
удовлетворения концепции TriviallyCopyable (TC) недостаточно, как показывает этот пример.base
является TC, но не безопасным для memcpy (из-за повторного использования дополнений для членов производного класса).
Меня особенно интересует, есть ли какие- либо условия наT
только этого достаточно (и не обязательно необходимо), не требуя условий src
а также dest
(который, как правило, не может быть определен статически).
1 В частности, мое предположение, что если они делают перекрытие, они по - прежнему безопасны для копирования в тех же условиях, наT
что касается std::memcpy
, но используя std::memmove
вместо. Если предположение неверно, это может быть частью ответа.
1 ответ
Для любого тривиально копируемого типа
T
, если два указателя наT
указать на отличныеT
объектыobj1
а такжеobj2
, где ниobj1
ниobj2
является подобъектом базового класса, если базовые байты ([intro.memory]), составляющиеobj1
копируются вobj2
,obj2
впоследствии будет иметь то же значение, что иobj1
.
Коротко:
каким условиям должен удовлетворять T, чтобы следующее было безопасным
T
должен быть легко копируемым; это единственное условие, котороеT
должен удовлетворить. Другое требование не является ограничениемT
, но ограничение на природу потенциально копируемых объектов. Это означает, что это не то, что вы можете определить статически.