它是否通过 memcpy 序列化 object 表示而不创建 object 就您不直接访问它包含的值而言是安全的?

Is it serializing object representations by memcpy without creating objects safe as far as you don't directly access the values it contains?

#include <cstdlib>
#include <cstring>
#include <iostream>

// C++03 only.
int main()
{
    std::allocator<unsigned char> alloc;

    double d = 8;
    unsigned char* buf = alloc.allocate(sizeof(double));
    std::memcpy(buf, &d, sizeof(double));

    double extract;
    std::memcpy(&extract, buf, sizeof(double));

    std::cout << extract << '\n';

    alloc.deallocate(buf, sizeof(double));
}

我已经为一个字节数组创建了存储空间,我从来没有通过初始化它来实现它,所以它的生命周期从未开始(在 C++03 中这基本上是不可能的,因为正确的方法是这样做是通过放置新的但对于数组它添加了一个你不知道它是什么的内存偏移量)

但是,我实际上并不需要 "directly read" 此存储中的数据,我通过 [=12] 完成 object 中的所有这些 copy-paste =]来电。

我对第二次 std::memcpy 电话有疑问。在值访问方面,是否认为 std::memcpy 正在读取每个 buf 数组元素的值,因此这个数组必须是存活的?

注意: 有人建议,这个问题可能是 Can memcpy be used for type punning? 的克隆。另一个问题是关于 C 的,这个问题也不是关于类型双关的,尽管它是相关的(我最初写了一个错误的问题标题,因为我误解了类型双关的实际含义)。我在这里询问传递给 memcpy 的 reading-from object 的精确语义,object 是否必须存在或实际上不需要。

std::allocator<unsigned char>::allocate 被指定为调用 ::operator new (C++03 lib.allocator.members/3)。所以这个问题与 基本相似,尽管之后没有尝试对值进行别名。

如果我们用字符赋值循环替换对 memcpy 的调用:unsigned char *p = (unsigned char *)&d; for (int i = 0; i < sizeof d; ++i) buf[i] = p[i]; 那么它肯定是未定义的行为,因为赋值运算符只有在左侧引用一个时才具有已定义的行为存在的对象。 .

但是对于 memcpy 版本,问题是:memcpy 与此字符分配循环相同,还是其他?

C++03 标准仅通过遵循 ISO C90 来定义 memcpy,即:

The memcpy function copies n characters from the object pointed to by s2 into the object pointed to by s1.

但不清楚如何解释这一点,因为 C 具有与 C++ 不同的对象模型。在 C 中 "object" 表示存储,而在 C++ 中 "object" 和 "storage" 表示不同的东西,并且在这个问题的代码中有没有对象的存储。

因此将情况描述为 "unspecified",尽管我认为 "not specified" 或 "unclear" 会更好,因为术语 "unspecified" C++中的具体含义。

脚注: 自 C++17 起,此主题没有实质性改变。但在 C++20 中,这将是明确定义的,accepted proposal detail.