#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 中这基本上是不可能的,因为正确的做法是通过放置新的,但对于数组,它添加了一个你不知道它是什么的内存偏移量)
但是,我实际上并不需要“直接读取”这个存储中的数据,我通过
std::memcpy
来完成所有这些对象的复制粘贴。来电。我的疑问是第二个
std::memcpy
称呼。在值(value)获取方面,是否认为 std::memcpy
正在读取每个 buf
的值数组元素,所以这个数组必须是活的?注意:有人建议,这个问题可能是 Can memcpy be used for type punning? 的克隆。 .另一个问题是关于 C 的,这个问题也不是关于类型双关语的,尽管它是相关的(我最初写了一个错误的问题标题,因为我误解了类型双关语的实际含义)。我在这里询问传递给
memcpy
的读取对象的精确语义。 ,该对象是否必须是事件的或实际上不需要。
最佳答案
std::allocator<unsigned char>::allocate
指定为调用 ::operator new
(C++03 lib.allocator.members/3)。所以这个问题与 "constructing" a trivially-copyable object with memcpy 基本相似。 ,尽管之后没有尝试别名值。
如果我们将调用替换为 memcpy
带有字符分配循环:unsigned char *p = (unsigned char *)&d; for (int i = 0; i < sizeof d; ++i) buf[i] = p[i];
那么它肯定是未定义的行为,因为赋值运算符仅在左侧引用存在的对象时才具有定义的行为。 See this answer for more detail .
然而对于 memcpy
版本,问题是:是memcpy
与此字符分配循环相同,还是其他?
C++03 标准只定义了 memcpy
通过推迟到 ISO C90,它说:
The memcpy function copies n characters from the object pointed to by s2 into the object pointed to by s1.
但目前尚不清楚如何解释这一点,因为 C 具有与 C++ 不同的对象模型。在 C 中,“对象”表示存储,而在 C++ 中,“对象”和“存储”表示不同的东西,并且在这个问题的代码中,存在没有对象的存储。
The answer by Shafik Yaghmour因此将这种情况描述为“未指定”,尽管我认为“未指定”或“不清楚”会是更好的描述,因为“未指定”一词在 C++ 中具有特定含义。
脚注:自 C++17 起,该主题没有任何实质性变化。但在 C++20 中,这将是明确定义的,accepted proposal detail .
关于c++ - 只要您不直接访问它包含的值,它是否通过 memcpy 序列化对象表示而不创建安全的对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60686589/