【发布时间】:2017-12-18 16:17:56
【问题描述】:
来自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
【问题讨论】:
-
“几乎可以保证效率低下” 标准从不保证任何容器移动分配操作都是恒定时间。它在要求中说得对:移动分配是线性的。移动 construction 是常数时间,而不是赋值。一般来说,人们不会经常进入现有容器。因此,这没什么大不了的。此外,移动操作不会复制元素。它只会移动它们。所以这和说没有移动分配是不一样的。