Ответ 1
Как использовать std::launder
для исправления этого кода? Нужно ли начинать и заканчивать каждый раз, когда используется новое место?
Из P0532R0 вы можете избежать необходимости вызывать launder()
, если возвращаемое значение места размещения new присваивается end
, Вам не нужно было бы менять указатель начала, если только вектор не был пуст, так как объект, на который указывает данный объект start
, все равно будет иметь активный срок службы с кодом, который вы указали.
В той же статье указывается, что launder()
является no-op, если только срок жизни объекта не закончился и был заменен новым объектом, поэтому использование launder()
не приведет к штрафу за производительность, если это не нужно:
[...] тип
std::launder(this)
эквивалентен именно этому, как указал Ричард Смит: Помните, чтоlaunder(p)
- это не-op, если p не указывает на объект, срок жизни которого закончился и где новый объект был создан в том же хранилище.
Текущие реализации stdlib, похоже, используют код, аналогичный тому, который был выше. Является ли поведение этих реализаций undefined?
Да. P0532R0 также обсуждает эту проблему, и контент похож на обсуждение в комментариях к вопросу: vector
не использует размещение новых напрямую, возвращаемое значение нового вызова места размещения теряется в цепочке вызовов функций векторному распределителю, и в любом случае размещение нового используется элемент за элементом, поэтому построение внутреннего векторного механизма не может использовать возвращаемое значение в любом случае. launder()
представляется инструментом, предназначенным для использования здесь. Однако тип указателя, указанный распределителем, не обязательно должен быть сырым типом указателя, а launder()
работает только для необработанных указателей. Текущая реализация в настоящее время undefined для некоторых типов; launder()
, похоже, не является подходящим механизмом для решения общего случая для контейнеров на основе распределителей.