Ответ 1
Я могу вспомнить несколько реальных сценариев, когда конструкция, разрешенная Стандартом, имеет смысл и требуется, однако; Сначала я попытаюсь ответить на этот вопрос с более широкой точки зрения, не затрагивая какой-либо конкретной проблемы.
ОБЪЯСНЕНИЕ
Распределители - это магические вещи, ответственные за распределение, построение, разрушение и освобождение памяти и объектов. Так как С++ 11, когда вступили в действие распределители состояния, распределитель может делать гораздо больше, чем раньше, но все сводится к ранее упомянутым четырем операциям.
Абонент имеет множество требований, один из которых - a1 == a2
(где a1
и a2
- распределители того же типа) должен давать true
только, если память, выделенная можно отменить другой [1].
Вышеуказанное требование operator==
означает, что два распределителя, сравнивающих одинаковые, могут делать что-то по-другому, если они все еще имеют взаимопонимание о распределении памяти.
Вышеприведенное означает, что стандарт позволяет propagate_on_container_*
быть равным std::false_type
; мы могли бы захотеть изменить содержимое двух контейнеров, у которых распределители имеют одинаковое поведение при освобождении, но оставим другое поведение (не связанное с управлением основной памятью).
[1] как указано в [allocator.requirements]p2
(таблица 28)
ИСТОРИЯ (SILLY)
Представьте, что у нас есть Allocator с именем Watericator, он собирает воду по требуемому распределению и передает ее в запрошенный контейнер.
Watericator - это Allocator с сохранением состояния, и при построении нашего экземпляра мы можем выбрать два режима;
-
использует Эрика, который забирает воду в пресную воду spring, а также измеряет (и сообщает) уровень и чистоту воды.
-
используйте Адама, который использует выталкивание на заднем дворе и не заботится о регистрации. Адам намного быстрее, чем Эрик.
Независимо от того, где вода приходит от нас, всегда распоряжаться ею таким же образом; путем полива наших растений. Даже если у нас есть один экземпляр, где Эрик снабжает нас водой (памятью), а другой, где Adam
использует краны, оба обойщика сравниваются с равными до operator==
.
Выделение, сделанное одним, может быть освобождено другим.
Вышеупомянутое может быть глупым similie, но представьте, что у нас есть распределитель, который регистрирует каждое распределение, и мы используем его в контейнере где-то в нашем коде, который нас интересует; мы позже хотим вывести элементы из этого контейнера в другой, но мы больше не заинтересованы во всех этих журналах.
Без разделителей с состоянием и возможность отключить propagate_on_container_*
, мы будем вынуждены либо 1) скопировать каждый задействованный элемент 2) застрять с записью (более не требуемой).