我在哪里可以找到 std::launder 的真正作用?
Where can I find what std::launder really does?
我试图了解 std::launder
的作用,我希望通过查找示例实现可以清楚地了解。
在哪里可以找到 std::launder
的示例实现?
当我查看 lbic++ 时,我看到类似
的代码
template<typename _Tp>
[[nodiscard]] constexpr _Tp*
launder(_Tp* __p) noexcept
{ return __builtin_launder(__p); }
这让我想到这是另一个编译器魔术函数。
这个函数 __builtin_launder
可以做什么,它只是添加一个标签来抑制编译器关于别名的警告吗?
是否有可能从 __builtin_launder
的角度理解 std::launder
或者它只是更神奇的编译器(挂钩)?
std::launder
的目的不是“抑制警告”,而是消除 C++ 编译器可能具有的假设。
别名警告试图通知您,您可能正在执行其行为未由 C++ 标准定义的操作。
编译器可以并且确实假设您的代码仅执行标准定义的操作。例如,它可以假定指向 const
值的指针一旦构造就不会更改。
编译器可能会使用该假设来跳过从内存中重新获取值(并将其存储在寄存器中),或者甚至在编译时计算它的值并根据它进行死代码消除。它可以假设这一点,因为任何它为 false 的程序都在执行未定义的行为,因此任何程序行为都在 C++ 标准下被接受。
std::launder
旨在允许您做一些事情,例如将指针指向合法修改的真正 const
值(例如,通过在其存储中创建一个新对象)并使用该指针在 以定义的方式修改(因此它指的是新对象)和其他特定和类似情况(不要假设它只是“消除别名问题”)。 __builtin_launder
在某种意义上将成为一个“noop”函数,但在另一种意义上它将改变围绕 可以生成什么样的汇编代码。有了它,就无法对其输出做出关于其输入可以达到什么价值的某些假设。一些在输入指针上是 UB 的代码在输出指针上不是 UB。
这是一个专家工具。就我个人而言,如果不进行大量标准研究并仔细检查我没有用错它,我是不会使用它的。添加它是因为有人证明某些操作无法以符合标准的方式合理地执行,并且它现在允许库编写者有效地执行它。
我试图了解 std::launder
的作用,我希望通过查找示例实现可以清楚地了解。
在哪里可以找到 std::launder
的示例实现?
当我查看 lbic++ 时,我看到类似
的代码 template<typename _Tp>
[[nodiscard]] constexpr _Tp*
launder(_Tp* __p) noexcept
{ return __builtin_launder(__p); }
这让我想到这是另一个编译器魔术函数。
这个函数 __builtin_launder
可以做什么,它只是添加一个标签来抑制编译器关于别名的警告吗?
是否有可能从 __builtin_launder
的角度理解 std::launder
或者它只是更神奇的编译器(挂钩)?
std::launder
的目的不是“抑制警告”,而是消除 C++ 编译器可能具有的假设。
别名警告试图通知您,您可能正在执行其行为未由 C++ 标准定义的操作。
编译器可以并且确实假设您的代码仅执行标准定义的操作。例如,它可以假定指向 const
值的指针一旦构造就不会更改。
编译器可能会使用该假设来跳过从内存中重新获取值(并将其存储在寄存器中),或者甚至在编译时计算它的值并根据它进行死代码消除。它可以假设这一点,因为任何它为 false 的程序都在执行未定义的行为,因此任何程序行为都在 C++ 标准下被接受。
std::launder
旨在允许您做一些事情,例如将指针指向合法修改的真正 const
值(例如,通过在其存储中创建一个新对象)并使用该指针在 以定义的方式修改(因此它指的是新对象)和其他特定和类似情况(不要假设它只是“消除别名问题”)。 __builtin_launder
在某种意义上将成为一个“noop”函数,但在另一种意义上它将改变围绕 可以生成什么样的汇编代码。有了它,就无法对其输出做出关于其输入可以达到什么价值的某些假设。一些在输入指针上是 UB 的代码在输出指针上不是 UB。
这是一个专家工具。就我个人而言,如果不进行大量标准研究并仔细检查我没有用错它,我是不会使用它的。添加它是因为有人证明某些操作无法以符合标准的方式合理地执行,并且它现在允许库编写者有效地执行它。