这个问题是 a comment 的后续问题。回答 another question .
考虑以下示例:
#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);
}
这个works(对于works的一些定义)。然而,标准告诉我们:
For any object (other than a base-class subobject) of trivially copyable type
T
, whether or not the object holds a valid value of typeT
, the underlying bytes making up the object can be copied into an array ofchar
,unsigned char
, orstd::byte
.
If the content of that array is copied back into the object, the object shall subsequently hold its original value. [ Example:#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
— end example ]
还有这个:
For any trivially copyable type
T
, if two pointers toT
point to distinctT
objectsobj1
andobj2
, where neitherobj1
norobj2
is a base-class subobject, if the underlying bytes making upobj1
are copied intoobj2
,obj2
shall subsequently hold the same value asobj1
. [ Example: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
— end example ]
在任何情况下,它都提到在缓冲区中复制一个可简单复制的类型,然后将其复制回原始类型的新实例中是允许的。
在上面的示例中,我做了类似的事情,另外我还将缓冲区复制到了一个新缓冲区中(这更类似于现实世界的情况)。
在问题顶部链接的评论中,作者说此行为未指定。另一方面,我看不到例如,如果不允许,我如何通过网络发送 int
并在另一端使用它(复制 int
到一个缓冲区,通过网络发送它,将其作为缓冲区接收并在 int
的实例中对其进行 memcpy - 或多或少是我在示例中所做的,中间没有网络)。
这是我错过的标准的其他一些项目符号允许的,还是真的未指定?
最佳答案
我觉得很好。
您已将 obj1
的底层字节复制到 obj2
中。两者都是微不足道的并且属于同一类型。您引用的散文明确允许这一点。
通过同样明确允许的重新解释为 char*
,将所述底层字节临时存储在大小正确且对齐正确的保存区域中,这一事实似乎并没有改变.它们仍然是“那些字节”。没有规定说复制必须是“直接的”才能满足这样的功能。
确实,这不仅是处理网络传输时完全常见的模式(当然,常规使用本身并不能使其正确),而且在历史上也很正常,标准将是 疯了不解释(这给了我所有需要的保证,它确实是有意的)。
我可以看到可能会有疑问,因为首先给出的规则是将这些字节复制回原始对象,然后再次给出将这些字节复制到新对象的规则。但我无法检测到这两种情况之间的任何逻辑差异,因此发现第一个引用的措辞在很大程度上是多余的。可能作者只是想清楚地表明这种安全性在两种情况下都适用。
关于c++ - 使用临时存储区 : is it allowed? 复制可简单复制的类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54531009/