Я проверил реализацию НКУ вектора, он читает:
vector(size_type __n, const value_type& __value,
const allocator_type& __a = allocator_type())
: _Base(__n, __a)
{ _M_fill_initialize(__n, __value); }
...
_M_fill_initialize(size_type __n, const value_type& __value)
{
this->_M_impl._M_finish =
std::__uninitialized_fill_n_a(this->_M_impl._M_start, __n, __value,
_M_get_Tp_allocator());
}
Таким образом, похоже, что информация о распределителе не уходит. Однако код uninitialized_fill_n_a
странный, он имеет две перегрузки (см. Ниже), один для общего распределителя и другой для std::allocator
.
Общие звонки, construct
и специальные для std::allocator
просто звонки std::uninitialized_fill()
.
Итак, мой вывод заключается в следующем,
1) все std::allocator
«s construct
s имеет тот же эффект, как и размещение нового и
2), которая не может быть принята для общих распределителей, или по крайней мере НКУ std::vector
не предполагает, что. (Согласно @Michael Burr, вы можете предположить это на C++ 03, к сожалению, он не упоминает C++ 11).
поэтому использование конструкция (std::allocator_traits<Alloc>::construct(alloc, pointer, value)
).
Мое личное мнение (после изучения этого), что
я) std::uninitialized_fill
неисправен, в который должен взять последний необязательный аргумент (или другой перегрузки) с распределителем,
II) в качестве обходной путь, внутри вашей детали реализации вы должны иметь функцию .uninitialized_fill(first, last, value, alloc)
, которая выполняет задание, включая обработку исключений (обратите внимание ниже, как конструкции разворачиваются с разрушением при сбое). .
III) Текущий std::unitialized_fill
довольно бесполезно, когда у вас есть информация о распределителем (и в основном вы должны переопределить его)
теперь код ссылки выше:
template<typename _ForwardIterator, typename _Size, typename _Tp,
typename _Allocator>
_ForwardIterator
__uninitialized_fill_n_a(_ForwardIterator __first, _Size __n,
const _Tp& __x, _Allocator& __alloc)
{
_ForwardIterator __cur = __first;
__try
{
typedef __gnu_cxx::__alloc_traits<_Allocator> __traits;
for (; __n > 0; --__n, ++__cur)
__traits::construct(__alloc, std::__addressof(*__cur), __x);
return __cur;
}
__catch(...)
{
std::_Destroy(__first, __cur, __alloc);
__throw_exception_again;
}
}
template<typename _ForwardIterator, typename _Size, typename _Tp,
typename _Tp2>
inline _ForwardIterator
__uninitialized_fill_n_a(_ForwardIterator __first, _Size __n,
const _Tp& __x, allocator<_Tp2>&)
{ return std::uninitialized_fill_n(__first, __n, __x); }
Что 'станд :: initialize_fill() '? Вы имеете в виду 'std :: uninitialized_fill()'? Функция 'initialize_fill()' не отображается нигде в стандарте C++, в отличие от 'uninitialized_fill()'. –
@ Insilico извините, это была опечатка. Спасибо. Я задал вопрос. – Martin
Это похоже на мой вопрос: http://stackoverflow.com/questions/9727556/is-uninitialized-copy-fillin-first-in-last-for-dest-aa-an-oversight-inthth, я делаю подумайте, что на самом деле, вероятно, безопасно использовать обычный 'uninitialized_fill' –