使用临时存储区复制简单的可复制类型:是否允许?

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, &copy, sizeof(int));

    assert(j == 42);
}
Run Code Online (Sandbox Code Playgroud)

适用于(对某些作品的定义).但是,标准告诉我们这个:

对于任何对象平凡复制的类型的(比基类的其他子对象)T时,对象是否保持类型的有效的值T,构成对象的底层字节可以被复制到的阵列char,unsigned charstd?::?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
Run Code Online (Sandbox Code Playgroud)

 - 结束例子]

还有这个:

对于任何平凡复制的类型T,如果两个指针T指向不同T对象obj1obj2,其中既不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
Run Code Online (Sandbox Code Playgroud)

 - 结束例子]

在任何情况下,它都提到在缓冲区中复制一个简单的可复制类型,然后将其复制回原始类型的新实例中是允许的.
在上面的例子中,我做了类似的事情,另外我还将缓冲区复制到一个新的缓冲区中(这类似于现实世界的情况).

在这个问题的顶部链接的评论,作者说,这种行为得以确认.另一方面,我无法看到例如如何int通过网络发送并在另一端使用它(如果不允许)(复制int到缓冲区,通过网络发送,接收它作为缓冲区和memcpy它在一个实例中int- 或多或少我在示例中所做的事情,中间没有网络).

这是由我错过了标准的其它一些子弹允许或这是真的得以确认

Lig*_*ica 6

它对我来说很好.

您复制的基本字节obj1obj2.两者都是微不足道的,属于同一类型.你引用的散文明确允许这一点.

事实上,所述基础字节被临时存储在正确大小且正确对齐的保持区域中,通过明确允许的重新解释char*,似乎不会改变这一点.它们仍然是"那些字节".没有规则说复制必须是"直接"才能满足这样的功能.

实际上,这不仅是处理网络传输时的一种完全常见的模式(传统使用当然不能使其正确),而且历史上正常的做法是标准会疯狂不考虑(这给了我所需要的所有保证,它确实是有意的).

我可以看到,如果首先将这些字节复制回原始对象,然后再将这些字节复制到新对象中,则可能会出现疑问.但我无法发现这两种情况之间存在任何逻辑差异,因此发现第一个引用的措辞在很大程度上是多余的.作者可能只是想清楚这种安全性在两种情况下同样适用.

  • 根据定义,这个规则只是传递:如果你有3个对象:obj1,obj2和obj3,那么比复制obj1 - > obj2使obj2与obj1完全相同.这意味着当你定义复制obj2 - > obj3的操作时,这意味着,由于第一次操作的结果,你可以将obj2改为obj1,并且没有区别:obj2 - > obj3 == obj1 - > obj3. (3认同)