Sprawdziłem wdrożenie GCC wektora, to brzmi:
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());
}
Tak, wygląda na to informacje o podzielniki nie odejdzie. Jednak kod uninitialized_fill_n_a
jest dziwny, ma dwa przeciążenia (patrz niżej), jeden dla ogólnego alokatora i drugi dla std::allocator
.
Połączenia ogólne, construct
i specjalne dla std::allocator
po prostu wywołuje std::uninitialized_fill()
.
Więc mój wniosek jest następujący,
1) wszystkie std::allocator
„s construct
s ma ten sam skutek, jak umieszczenie nowego i
2), że nie można przyjąć dla podzielników generycznych, albo przynajmniej GCC std::vector
nie zakłada tego. (Według Michaela Burra można założyć to w C++ 03, niestety nie wspomina on o C++ 11).
Dlatego używajcie konstruktu (to jest std::allocator_traits<Alloc>::construct(alloc, pointer, value)
).
Moja osobista opinia (po zbadaniu tego), że
i) std::uninitialized_fill
jest uszkodzony, w które należy podjąć ostatnią opcjonalny argument (lub inny przeciążenie) z podzielnika,
II), jak obejście, wewnątrz szczegółów implementacji powinieneś mieć funkcję .uninitialized_fill(first, last, value, alloc)
, która wykonuje zadanie, w tym obsługę wyjątków (zwróć uwagę poniżej, w jaki sposób rozwijane są konstrukcje z niszczy podczas awarii). .
iii) Aktualny std::unitialized_fill
jest całkiem bezużyteczny, jeśli masz informacje o podzielniki (iw zasadzie trzeba go reimplement)
teraz kod mowa powyżej:
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); }
Co 'std :: initialize_fill() '? Masz na myśli 'std :: uninitialized_fill()'? Funkcja 'initialize_fill()' nie pojawia się nigdzie w standardzie C++, w przeciwieństwie do 'uninitialized_fill()'. –
@Insilico przepraszam, to była literówka. Dziękuję Ci. Naprawiłem pytanie. – Martin
Wydaje się, że jest to związane z moim pytaniem: http://stackoverflow.com/questions/9727556/is-uninitialized-copy-fillin-first-in-last-for-dest-aa-an-oversight-in-, robię myślę, że w rzeczywistości prawdopodobnie bezpiecznie jest użyć zwykłego 'uninitialized_fill' –