2016-07-25 3 views
4

Я мог бы неправильно понять некоторые понятия о распределителе. Но я действительно не знаю, зачем нужен аргумент std::size_t, который будет передан в allocate, чтобы указать количество объектов, которые будут выделены. Используется ли аргумент для распределения областей памяти, таких как массивы или векторы?Как пользовательский распределитель знает, указывает ли указатель на массив?

Если они, то может ли мой пользовательский распределитель узнать, указывает ли ранее возвращаемый указатель на область или только объект? Является ли мой распределитель ответственным за запись этих указателей?

Если они не, то зачем нам этот аргумент?

+0

Помогает ли это? http://en.cppreference.com/w/cpp/memory/allocator/allocate – NathanOliver

ответ

5

allocator_traits<YourAllocator<T>>::allocate ожидается выделение памяти для непрерывной последовательности из N объектов типа T. N задается параметром size_t.

Если это так, то как мой пользовательский распределитель знает, указывает ли ранее возвращаемый указатель на область или только объект?

Что такое «ранее возвращенный указатель»?

Ваш распределитель будет выслан, когда нужно выделить и когда освободить памяти. Когда происходит освобождение, it will be told what N was for the allocation that is being deallocated. Ваш распределитель не должен отслеживать какие-либо указатели.

+0

Мой плохой, и из-за этого произошла ужасная утечка памяти при передаче в контейнеры STL. Я написал подпись как 'void deallocate (pointer ptr, std :: size_t dummy = 1)': - \ Спасибо – YiFei

0

Предполагая, что вы говорите о std :: allocator здесь. Документация довольно ясно:

T* std::allocator::allocate(std::size_t n);

Выделяет п * SizeOf (T) байты неинициализированного хранения [...]

Таким образом, ответ на ваш вопрос будет: Да, аргумент используется для выделения областей памяти, таких как массивы или векторы.

И для прослеживания вопроса: Нет, вам не нужно следить за возврат указателей, поскольку std::allocator::deallocate гарантированно будет вызываться с таким же, как nstd::allocator::allocate был для любого из возвращаемых указателей.

void std::allocator::deallocate(T* p, std::size_t n);

освобождает память, на который ссылается указатель р, который должен быть указатель, полученный предыдущим вызовом выделить(). Аргумент n должен быть равен первому аргументу вызова allocate(), изначально созданного p; в противном случае поведение не определено.

+0

Я не вижу никакой гарантии здесь. Вам нужно передать тот же указатель, который был создан с помощью allocate, и вам нужно передать правильный размер, иначе это UB. – NathanOliver

+0

@NathanOliver Я думаю, что они ссылаются на гарантию, предлагаемую стандартными контейнерами: если вы создаете пользовательский распределитель для 'std :: vector', то' std :: vector' всегда (теоретически) будет соблюдать контракты вашего распределителя и вызовите 'deallocate' с теми же' p' и 'n', что и в' allocate'. – KABoissonneault

+0

@KABoissonneault Ah. В этом есть смысл. – NathanOliver

Смежные вопросы