gpt4 book ai didi

c++ - std::unitialized_copy 是否有未定义的行为?

转载 作者:行者123 更新时间:2023-12-01 14:53:27 24 4
gpt4 key购买 nike

为类类型 T 的对象构造缓冲区(例如环形缓冲区)时的一个常见习惯用法是使用从 std::malloc() 或 operator new() 获得的内存地址初始化 T* 对象,然后在该缓冲区使用placement new 按需使用,使用T 指针上的指针算术遍历内存块。

虽然似乎不太可能有任何编译器无法使用它(它确实适用于 g++ 和 clang++),但在我看来,严格来说这可能具有未定义的行为。这是因为 C++17 的 §8.7/4 似乎只允许对数组进行指针运算,并且 malloc、operator new 或 operator new[] 返回的内存块不是数组——据我所知,只有 new[ ] 表达式可以在动态内存中创建一个数组,从而在构造点将其完全初始化。

这也让我想到 std::uninitialized_copy 的引用实现对于动态分配的未初始化内存具有未定义的行为,因为它在 C++17 的 §23.10.10.4/1 中的引用实现在目标迭代器上使用指针算术,这将在这里做一个指针。

如果未初始化的内存是非动态获得的,例如使用 C++17 的 §4.5/3 所允许的 unsigned char 或 std::byte 的对齐数组,则可以说这同样适用于 std::uninitialized_copy,因为在§8.7/4 暗示执行算术的目标指针类型应该是数组元素类型(unsigned char 或 std::byte),而不是使用placement new 在其中构造的类型。

这似乎令人惊讶。谁能指出这个推理中的缺陷(如果有的话)。

最佳答案

是的,从 malloc 返回的指针的指针运算或 operator new如果没有先前的数组放置新(它本身不能可靠地完成),则具有未定义的行为,使用 std::unintialized_copy 也是如此在它上面,它被定义为表现得好像这个指针算术已经完成了。

您能做的最好的事情是创建一个 std::byte (或 unsigned char )数组作为存储,直接使用 new[] ,然后将新的单个对象放置到该存储数组中,这将使这些对象嵌套在缓冲区数组中。

存储数组上的指针算法是明确定义的,因此您可以使用 std::launder 访问指向存储数组中单个对象位置的指针。或者通过使用从placement-new 返回的指针,您可以获得指向嵌套对象的指针。即使这样,您也无法对指向嵌套对象的指针使用指针算术,因为它们不会形成数组。

见论文P0593R5Implicit creation of objects for low-level object manipulation有关这种令人惊讶的未定义行为的更多示例以及在 future 对其进行定义的建议。

关于c++ - std::unitialized_copy 是否有未定义的行为?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60465235/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com