sky*_*ack 12 c++ language-lawyer c++17
请考虑以下示例:
#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);
}
Run Code Online (Sandbox Code Playgroud)
这适用于(对某些作品的定义).但是,标准告诉我们这个:
对于任何对象平凡复制的类型的(比基类的其他子对象)
T时,对象是否保持类型的有效的值T,构成对象的底层字节可以被复制到的阵列char,unsigned char或std?::?byte.
如果将该数组的内容复制回对象,则该对象应随后保持其原始值.[例如:Run Code Online (Sandbox Code Playgroud)#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.[例如:Run Code Online (Sandbox Code Playgroud)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- 或多或少我在示例中所做的事情,中间没有网络).
这是由我错过了标准的其它一些子弹允许或这是真的得以确认?
它对我来说很好.
您复制的基本字节obj1成obj2.两者都是微不足道的,属于同一类型.你引用的散文明确允许这一点.
事实上,所述基础字节被临时存储在正确大小且正确对齐的保持区域中,通过明确允许的重新解释char*,似乎不会改变这一点.它们仍然是"那些字节".没有规则说复制必须是"直接"才能满足这样的功能.
实际上,这不仅是处理网络传输时的一种完全常见的模式(传统使用当然不能使其正确),而且历史上正常的做法是标准会疯狂不考虑(这给了我所需要的所有保证,它确实是有意的).
我可以看到,如果首先将这些字节复制回原始对象,然后再将这些字节复制到新对象中,则可能会出现疑问.但我无法发现这两种情况之间存在任何逻辑差异,因此发现第一个引用的措辞在很大程度上是多余的.作者可能只是想清楚这种安全性在两种情况下同样适用.