c++ - 使用临时存储区 : is it allowed? 复制可简单复制的类型

标签 c++ language-lawyer c++17

这个问题是 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, &copy, 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 type T, the underlying bytes making up the object can be copied into an array of char, unsigned char, or std​::​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 to T point to distinct T objects obj1 and obj2, where neither obj1 nor obj2 is a base-class subobject, if the underlying bytes making up obj1 are copied into obj2, obj2 shall subsequently hold the same value as obj1. [ 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/

相关文章:

c++ - 如何在 Linux(Ubuntu OS)中检测 C++ 应用程序的内存泄漏?

c++ - constexpr 类中的引用字段

c++ - 这些关于 GCC 优化的评论是否有效?

c++ - 如何为模板类的 const ref 成员定义 move 赋值运算符

c - argv 中指向字符串的指针是否可修改?

c - switch-case 中有效但毫无值(value)的语法?

c++ - 使用结构化绑定(bind)标记为 const 的变量不是 const

c++ - 为什么 std::visit 必须有单一的返回类型?

c++ - 获取最近的路径图

c++ - 将固定大小的特征矩阵作为参数传递给调用动态大小矩阵的函数