Этот вопрос является продолжением комментария к ответу другого вопроса .
Рассмотрим следующий пример:
#include <cstring>
#include <type_traits>
#include <cassert>
int main() {
std::aligned_storage_t<sizeof(void*), alignof(void*)> storage, copy;
int i = 42;
std::memcpy(&storage, &i, sizeof(int));
copy = storage;
int j{};
std::memcpy(&j, ©, sizeof(int));
assert(j == 42);
}
Это работает (для некоторых определений работает ).Однако стандарт сообщает нам следующее:
Для любого объекта (кроме подобъекта базового класса) типа тривиально копируемого типа T
независимо от того, содержит ли объект допустимое значение типа T
, лежащие в основе байты, составляющие объект, могут быть скопированы в массив char
, unsigned char
или std::byte
.
Если содержимое этого массива копируется обратно в объект, объект должен впоследствии содержатьего первоначальная стоимость.[Пример:
#define N sizeof(T)
char buf[N];
T obj; // obj initialized to its original value
std::memcpy(buf, &obj, N); // between these two calls to std::memcpy, obj might be modified
std::memcpy(&obj, buf, N); // at this point, each subobject of obj of scalar type holds its original value
- конец примера]
И это:
Для любого тривиально копируемого типа T
, если два указателя наT
указывают на различные T
объекты obj1
и obj2
, где ни obj1
, ни obj2
не являются подобъектами базового класса, если нижележащие байты, составляющие obj1
, копируются в obj2
,obj2
должен впоследствии иметь то же значение, что и obj1
.[Пример:
T* t1p;
T* t2p;
// provided that t2p points to an initialized object ...
std::memcpy(t1p, t2p, sizeof(T));
// at this point, every subobject of trivially copyable type in *t1p contains
// the same value as the corresponding subobject in *t2p
- конец примера]
В любом случае упоминается, что копируется тривиально копируемый тип в буфер, а затем копируется обратно в новый экземплярдопускается использование оригинального типа.
В приведенном выше примере я делаю нечто подобное, плюс копирую также буфер в новый буфер (это немного больше похоже на случай из реальной жизни).
В комментариях, связанных сВ верхней части вопроса автор говорит, что это поведение недостаточно указано .С другой стороны, я не вижу, например, как я могу отправить int
по сети и использовать его на другом конце, если это не разрешено (скопировать int
в буфер, отправить его по сети, получитьэто как буфер и memcpy это в экземпляре int
- более или менее то, что я делаю в этом примере, без сети между ними.
Это разрешено некоторыми другими пулями стандарта, который я пропустилили это действительно недооценено ?