我正在使用 Howard Hinnant 的漂亮的基于竞技场的小分配器short_alloc。
让我感到震惊的是,可以使用通常的快速移动分配(即,获取目标的资源)来完成从已经超出其竞技场并因此在堆上分配的向量的移动分配。然而,这种情况并非如此:
typedef arena<16> arena_type;
typedef short_alloc<int, 16> alloc_type;
typedef std::vector<int, alloc_type> vec_type;
arena_type arena1, arena2;
vec_type vec1(alloc_type(arena1)), vec2(alloc_type(arena2));
vec1.resize(100);
void* data = vec1.data();
vec2 = std::move(vec1);
assert(vec2.data() == data); // fails
正如这个答案中所解释的,这是由于向量的移动赋值运算符比较了两个分配器(注意propagate_on_container_move_assignment
是std::false_type
)。由于两个分配器比较不相等(因为它们具有不同的 arena),因此目标向量需要分配内存并一一移动值。
通过将相等运算符更改为
template <class T1, size_t N1, class T2, size_t N2>
bool operator==(const short_alloc<T1, N1>& x, const short_alloc<T2, N2>& y) noexcept
{
return N1 == N2 && (&x.a_ == &y.a_ || y.a_.on_heap());
}
whereon_heap()
检查分配器是否没有使用它的 arena。
这个解决方案看起来相当骇人听闻(例如,请注意,平等不是对称的),我可以/我会这样做吗?有没有优雅的解决方案?