c++ - 只要您不直接访问它包含的值,它是否通过 memcpy 序列化对象表示而不创建安全的对象?

标签 c++ language-lawyer lifetime c++03

#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/

相关文章:

c++ - 类模板特化中的decltype

c++ - 重载和覆盖如何协同工作?

c - 保证指向标准函数的指针不相等?

c++ - C++17 之前的类模板参数推导

rust - 为什么不能在结构定义中省略生命周期?

rust - 跨多个特征借用数据时如何编写适当的通用函数签名

c++ - QMap::contains() 和 QMap::value() 找不到现有的键值对

c++ - 另一个虚拟模板解决方法

c - printf 长度修饰符 %L 是标准的(或 future 的标准)吗?

rust - 什么是非词汇生命周期?