在 C 编程领域,使用像 memcpy 这样的按位复制方法构造普通可复制对象有引发了关于对象生命周期的争论。问题出现了:下面代码中 b 指向的对象是否保证有明确定义的生命周期?
struct T { int x, y; }; int main() { void *buf = std::malloc(sizeof(T)); if (!buf) return 0; T a{}; std::memcpy(buf, &a, sizeof a); T *b = static_cast<T *>(buf); b->x = b->y; free(buf); }
未解决的问题
C尽管正在进行讨论和提出建议,但标准在这个问题上仍然含糊不清。由于缺乏明确的指导,这个问题没有得到解答,这对基于语义的分析工具、优化器和生命周期跟踪都有影响。
N3751 提案
N3751 建议识别 memcpy涉及不同的简单可复制对象作为对象构造的操作,支持二进制 IO,同时保留生命周期分析
C 14 标准
C 14 标准将对象创建定义为通过定义、new 表达式或实现认为有必要时发生。当前语言没有明确解决使用 memcpy 来构造对象的问题。
std::vector 实现
std::vector 的当前实现突出了一个实际场景出现此问题的地方,会导致未定义的行为。
提案 p0593:隐式对象创建
提案 p0593 旨在通过显式定义隐式创建对象的场景(包括调用 malloc 和 memcpy)来解决这种歧义。它提出了按需创建对象的机制,为程序提供定义的行为。然而,该提案仍在审查中。
结论
使用 memcpy 构建对象的状态仍然是 C 社区中持续争论的话题。在达成共识并更新标准之前,提供的示例之类的代码行为仍然未定义,可能会导致不可预测的程序行为。
以上是memcpy 在 C 中构造普通可复制对象吗?的详细内容。更多信息请关注PHP中文网其他相关文章!