Из http://en.cppreference.com/w/cpp/memory/polymorphic_allocator:
polymorphic_allocator
не распространяется на назначение копии контейнера, назначение перемещения или обмен. В результате назначение перемещенияpolymorphic_allocator
-использующего контейнера может привести к ошибке, а замена двухpolymorphic_allocator
-использующих контейнеров, распределители которых не сравнивают одинаковые результаты, приводит к неопределенному поведению.
Зачем мне такое поведение? Это не только вводит необоснованное неопределенное поведение при подкачке, но и, что более важно для моих целей, подразумевает, что 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
. В итоге это привело к плохим последствиям, например, при назначении перемещения вектору теперь копируются его данные; но у вас не так много оборванных указателей на ресурсы памяти. (Некоторые да, но не так много.)
P.S. Я уже вижу, что вы можете избежать копирования/удаления, заранее настроив распределитель, например так:
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