he comprobado la aplicación de GCC vector, se lee:
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());
}
Por lo tanto, parece que la información del asignador no desaparece. Sin embargo, el código de uninitialized_fill_n_a
es extraño, tiene dos sobrecargas (ver a continuación), una para el asignador genérico y otra para std::allocator
.
Las llamadas genéricas, construct
y las especiales para std::allocator
simplemente llaman a std::uninitialized_fill()
.
Por lo tanto, mi conclusión es la siguiente,
1) todos std::allocator
's construct
s tienen el mismo efecto que la colocación de nuevo y
2) que no puede ser asumida por los asignadores de genéricos, o al menos GCC std::vector
no supone eso. (Según @Michael Burr puedes asumir esto en C++ 03, lamentablemente no menciona C++ 11).
por lo tanto, use construct (es decir, std::allocator_traits<Alloc>::construct(alloc, pointer, value)
).
Mi opinión personal (después de investigar esto), es que
i) std::uninitialized_fill
es defectuoso, en el que debe tomar un último argumento opcional (u otra sobrecarga) con el asignador,
ii) una solución alternativa, dentro de los detalles de su implementación debe tener una función .uninitialized_fill(first, last, value, alloc)
que hace el trabajo, incluido el manejo de excepciones (observe a continuación cómo se desenrollan las construcciones con destruye al fallar). .
iii) actual std::unitialized_fill
es bastante inútil cuando se tiene información sobre el asignador (y, básicamente, tiene que volver a implementar es)
ahora el código de referencia más arriba:
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); }
Qué es 'std :: initialize_fill() '? ¿Quiere decir 'std :: uninitialized_fill()'? La función 'initialize_fill()' no aparece en ningún lugar en el estándar C++, a diferencia de 'uninitialized_fill()'. –
@Insilico lo siento, fue un error tipográfico. gracias. Arreglé la pregunta. – Martin
Esto parece estar relacionado con mi pregunta: http://stackoverflow.com/questions/9727556/is-uninitialized-copy-fillin-first-in-last-for-dest-aa-an-oversight-in-th, lo hago piense que en realidad probablemente sea seguro usar 'uninitialized_fill' ordinario –