Ответ 1
Выполняется с вызовом функции allocator allocate() для получения необработанной памяти и последующего вызова структуры allocator (iterator, val) для создания элемента путем копирования с использованием нового места размещения, то есть что-то похожее на это:
/* approach similar to std::uninitialized fill taken */
template<typename T, typename A >
vector<T,A>::vector( size_type n, const T& val, const A& a) : alloc( a) // copy the allocator
{
/* keep track of which elements have been constructed
* and destroy those and only those in case of exception */
v = alloc.allocate( n); // get memory for elements
iterator p; // declared before try{} so it is still valid in catch{} block
try {
iterator end = v + n;
for( p = v; p != end; ++p)
alloc.construct( p, val); /* construct elements (placement new):
e g. void construct( pointer p, const T& val)
{ ::new((void *)p) T( val); } */
last = space = p;
} catch( ...) {
for( iterator q = v; q != p; ++q)
alloc.destroy( q); /* destroy constructed elements */
alloc.deallocate( v, n); /* free memory */
throw; /* re-throw to signal constructor that failed */
}
}
В С++ распределитель используется для изоляции исполнителей алгоритмов и контейнеров, которые должны выделять память из деталей физической памяти.
Подход, использующий uninitialized_fill, также можно взять:
std::uninitialized_fill( v, v + n, val); /* copy elements with (placement new):
e g. void construct( pointer p,
const T& val)
{ ::new((void *)p) T( val); } */
Это описано более подробно в Bjarne Stroustrup "С++... 3rd edition". Здесь приведен пример, основанный на этом.