为什么'std::p mr::p olymorphic_allocator'不会在容器移动时传播?
Why does `std::pmr::polymorphic_allocator` not propagate on container move?
来自 http://en.cppreference.com/w/cpp/memory/polymorphic_allocator:
polymorphic_allocator
不会在容器副本分配、移动分配或交换时传播。因此,polymorphic_allocator
-using 容器的移动分配可能会抛出,并交换两个polymorphic_allocator
-using 容器,其分配器不会在未定义的行为中比较相等的结果。
我为什么要这种行为?这不仅似乎在交换中引入了无端的未定义行为,而且更重要的是,对于我的目的而言,它意味着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
的引用。这最终产生了不良影响,例如移动赋值矢量现在复制其数据;但是你最终不会得到那么多指向内存资源的悬而未决的指针。(有些是的,但没有那么多。
附言我已经看到您可以通过提前设置分配器来避免复制/抛出,如下所示:
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
是运算符的静态属性。由于 PMR 在运行时之前无法知道它们是否可以传播存储,因此容器必须将其移动分配运算符指定为抛出移动分配。
在运行时,它实际上可以决定传播是否可能。如果可能的话,它将采取更有效的道路。
- 将对象移动到std::shared_ptr
- 何时在引用或唯一指针上使用移动语义
- 如何从具有移动语义的类对象中生成共享指针
- 将shared_ptr移动到<StructA>shared_ptr<变体<结构A、结构 B>>
- C / C++ 移位/偏移/向左或向右移动位图?
- MSVC将仅移动结构参数解释为指针
- 自定义先决条件对移动分配运算符有效吗
- 返回值优化:显式移动还是隐式
- 当有分配器意识的容器被复制/移动时,反弹分配器是否被复制/移走
- 为什么复制而不是移动数据元素?
- 可以使用移动语义更改或改进此C++代码吗?
- 使lambda不可复制/不可移动
- c++在使用指针时移动语义
- 将QGraphicsItem的移动区域限制在多边形区域内
- SendInput()鼠标移动计算
- 按值 C++ 返回时进行双倍移动
- 移动二维数组中的字符
- 为什么不调用移动构造函数?(默认情况下只有构造器,没有别的)
- 安全到标准:移动会员?
- 为什么'std::p mr::p olymorphic_allocator'不会在容器移动时传播?