gpt4 book ai didi

c++ - 为什么 `std::pmr::polymorphic_allocator` 不会在容器移动时传播?

转载 作者:可可西里 更新时间:2023-11-01 18:30:49 28 4
gpt4 key购买 nike

来自 http://en.cppreference.com/w/cpp/memory/polymorphic_allocator :

polymorphic_allocator does not propagate on container copy assignment, move assignment, or swap. As a result, move assignment of a polymorphic_allocator-using container can throw, and swapping two polymorphic_allocator-using containers whose allocators do not compare equal results in undefined behavior.

为什么我会想要这种行为?这不仅似乎在交换上引入了无端的未定义行为,而且对于我的目的而言更重要的是,它暗示 std::pmr::vector 实际上是一种不可移动赋值的类型。我的意思是,它是可移动赋值的,但这几乎肯定是低效的。

std::vector<int> v = {1, 2, 3};
std::vector<int> w;
w = std::move(v); // nocopy, nothrow

std::pmr::monotonic_buffer_resource mr(1000);
std::pmr::vector<int> v( {1, 2, 3}, &mr );
std::pmr::vector<int> w;
w = std::move(v); // yescopy, yesthrow

我的猜测是,这是处理所有权问题的原始尝试。在上面的第二个示例中,v 持有对 mr 的引用,但 v 实际上并不拥有 mr 。允许非拥有引用在整个系统中未经检查地传播将倾向于引入许多细微的错误。因此,设计者没有发明拥有 分配器,而是简单地决定不传播mr 的引用。这最终会产生不良影响,例如移动分配 vector 现在会复制其数据;但是您最终不会得到那么多指向内存资源的悬空指针。 (一些是的,但没那么多。)


附言我确实已经看到您可以通过提前设置分配器来避免复制/抛出,如下所示:

std::pmr::monotonic_buffer_resource mr(1000);
std::pmr::vector<int> v( {1, 2, 3}, &mr );
std::pmr::vector<int> w(v.get_allocator());
w = std::move(v); // nocopy, nothrow

最佳答案

allocator_traits<>::propagate_on_container_copy/move_assignment/swap是分配器的静态 属性。根据设计,多态分配器的属性在运行时 定义。有些多态分配器可以传播到其他分配器,有些则不能。

因此,不可能在编译时知道这些属性。所以 PMR 分配器必须在编译时假设最坏的情况:没有传播。

让我们以您的示例为例,进行更改:

std::pmr::monotonic_buffer_resource mr(1000);
std::pmr::vector<int> v( {1, 2, 3}, &mr );
std::pmr::vector<int> w;
auto a1 = w.get_allocator();
w = std::move(v);
assert(w.get_allocator() == a1);

C++ 标准要求这不断言。赋值不会移动容器的分配器;这就是容器分配与 C++ 中的分配器一起工作的方式。

因此,目标容器的分配器要么可以处理源容器的内存,要么不能。如果不能,则目标容器必须分配内存并从源复制/移动对象。

移动赋值运算符是否为noexcept or not 是运算符的静态属性。由于 PMR 直到运行时才知道它们是否可以传播存储,因此容器必须将其移动赋值运算符指定为抛出移动赋值。

在运行时,它实际上可以决定传播与否。如果可能的话,它会选择更有效的路径。

关于c++ - 为什么 `std::pmr::polymorphic_allocator` 不会在容器移动时传播?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45088131/

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