Копируются / перемещаются распределительные отскок, когда контейнер, распознающий распределитель, копируется / перемещается? - PullRequest
3 голосов
/ 20 февраля 2020

Этот вопрос является скорее любопытством, чем практическим вопросом.

В C ++ многие контейнеры "основаны на узлах". Это означает, что для хранения они не могут на самом деле использовать распределитель, переданный им, вместо этого они делают что-то вроде:

typedef typename A::template rebind<node>::other node_allocator_type

и, по-видимому, создают элемент этого типа, как этот или Аналогично:

node_allocator_type node_allocator;

Чтобы создать распределитель, который может распределять узлы. Отлично, все это имеет смысл, но у меня есть вопрос о том, что происходит во время копирования / перемещения контейнера, если контейнер действительно «распознает распределитель», поддерживая распределители с сохранением состояния.

Копируется ли распределитель узлов / тоже переехал? Это имеет смысл на поверхностном уровне, но что происходит, когда мы сталкиваемся с конструктором копирования / перемещения, где пользователь может указать новый распределитель, подобный этому?

list( const list& other, const Allocator& alloc );
list( list&& other, const Allocator& alloc );

В этом случае other allocator не копируется и не перемещается, поэтому вновь созданный список получает совершенно новый node_allocator вместе с копированием / перемещением alloc?

Это, очевидно, деталь реализации, но мне интересно что такое «правильно» и что делают типичные реализации. Я также признаю, что pre-C ++ 11, распределители с сохранением состояния не очень хорошо поддерживаются, и поэтому это не проблема.

1 Ответ

1 голос
/ 20 февраля 2020

Предполагается, что копирующие распределители (даже распределители с сохранением состояния) являются дешевой операцией; если у них есть какие-либо связанные ресурсы, они должны храниться по ссылке . Кроме того, распределители отскока могут быть построены посредством копирования, и они сравниваются равными исходному распределителю; см. a == b в Cpp17Allocator требования .

В результате контейнер полностью свободен для хранения Allocator, Allocator::rebind<void>, или Allocator::rebind<node_type>, и копировать-преобразовывать между ними по мере необходимости при выделении узлов, при построении перемещения, при возврате (prvalue!) из get_allocator(), et c. Обычно libstdc ++ хранит, например, и Allocator::rebind<node_type>.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...