繁体   English   中英

即使在 C++20 中 std::memcpy 也不是 constexpr 的原因是什么?

[英]What is the reason for std::memcpy not being constexpr even in C++20?

我知道在编译时并不总是可以复制任意的内存块,但是既然我们得到了 constexpr 容器、虚拟方法和算法,那么为什么不使用 memcpy 呢? 这也是一种算法。

此外,

  • C++20 std::bit_cast看起来很像std::memcpy解决方法reinterpret_cast但它是constexpr
  • 使用迭代器的std::copy被标记为 C++20 的constexpr ,因此复制对于类型来说是可能的。

用法是在constexpr函数中复制或只是“重新解释”变量/数组,前者不是由std::bit_cast AFAIK 解决的。 特别是这个问题和我的答案想使用它。

  • 为什么std::bit_cast可以是 constexpr 而std::memcpy不能?
  • 它是否与使用空指针而不是类型化引用的 memcpy 有关?
  • 实际上不必复制任何东西?
  • C 向后兼容?
  • 也许是因为不支持“指向 constexpr 内存的指针”? 但同样适用于std::bit_cast的引用参数和std::copy迭代器。

C++20 bit_cast vs reinterpret_cast 的相关答案从某处简要引用:

此外,目前不可能实现 constexpr 位转换函数,因为 memcpy 本身不是 constexpr。 将建议的函数标记为 constexpr 不需要或阻止 memcpy 成为 constexpr,但需要编译器支持。 这使得实现可以自由地使用他们自己的内部解决方案(例如,LLVM 有一个位播操作码)。

但它没有详细说明不使其成为 constexpr。

请注意,我不问为什么std::bit_cast存在。 我喜欢它,它提供了一个明确的意图,而不是std::memcpy解决方法。

运行时代码中的 C++ 对象模型通常处理得有些松散。 它有相当严格的规则,但有一堆后门要么被允许,要么被宣布为 UB。 后者意味着您仍然可以编写代码来执行此操作,但 C++ 对该代码的行为没有任何保证。

在不断评估(又名:代码的编译时执行)中,情况并非如此。 constexpr的限制专门用于允许对象模型成为您必须遵循的真实事物,没有可行的后门。 甚至它偶尔允许的那些也明确要求格式错误并产生编译错误,而不是静默 UB。

基本上在运行时,您可以将内存视为存储字节。 在编译时,你不能 你不被允许。 即使在 C++20 中添加了constexpr代码中的动态分配,您也不会玩很多通常会玩那种东西的游戏。

memcpy处理存储字节数,来回复制它们而不知道它们的含义。 bitcast知道源对象和目标对象,除非源对象和目标对象适合bitcast ing(即:可简单复制),否则它不允许您这样做。

如果您希望它在编译时工作, bitcast对这两个对象的内容也有非常具体的限制 特别是,您不能bitcast指针或包含任何类型指针的任何对象进行位转换。 或者参考。

这是因为编译时的指针不仅仅是地址。 为了捕获 UB,编译时指针必须知道它指向的对象的真实动态类型。 所以在编译时不允许只转换地址的指针转换。

这更多是评论然后是答案,因为我只是引用了P0202R0 中写的内容:将 Constexpr 修饰符添加到函数和标题中,但我在这里写的不符合评论:

B. std::memmovestd::memcpy必须添加 constexpr
std::memmovestd::memcpy接受void*const void*参数。 这使得它们无法在纯 C++ 中实现为constexpr ,因为常量表达式无法根据 [expr.const] 评估从类型cv void *到指向对象类型的转换。
然而,这些函数不仅流行,而且在标准库中广泛使用以获得更好的性能。 不使它们 constexpr 将迫使标准库开发人员无论如何都为它们提供编译器内在函数。 这是必须完成的艰难步骤。

[expr.const]的相关部分:

8.6 常量表达式 [expr.const]
[…]表达式e核心常量表达式,除非按照抽象机 (6.8.1) 的规则对e求值,会求值以下表达式之一:
[…]
(2.13) — 从cv void*类型到指向对象类型的转换;

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM