Работа с вашим вторым вопросом: первого
Если присутствует, станд :: size_t аргумент размер должен равняться размером аргумента, передаваемые функции распределения, возвращающих PTR.
Таким образом, любое дополнительное пространство, которое может быть выделено, является обязанностью библиотеки времени выполнения, а не кода клиента.
Первый вопрос сложнее ответить хорошо. Основная идея - (или, по крайней мере, кажется), что размер блока часто не сохраняется непосредственно рядом с самим блоком. В большинстве случаев размер блока записывается и никогда не записывается снова до тех пор, пока блок не будет освобожден. Чтобы избежать использования данных, загрязняющих кеш при работе блока, его можно хранить отдельно. Затем, когда вы идете на освобождение блока, размер часто выгружается на диск, поэтому чтение его обратно происходит довольно медленно.
Это также довольно распространено, чтобы не допускать явного явного сохранения размера каждого блока. Распределитель будет часто иметь отдельные пулы для разных размеров блоков (например, полномочия 2 от 16 или около того примерно до пары килобайт или около того). Он будет выделять (справедливый) большой блок из ОС для каждого пула, а затем выделять части этого большого блока пользователю. Когда вы возвращаете адрес, он в основном ищет этот адрес через разные размеры пулов, чтобы найти, из какого пула он пришел. Если у вас много пулов и много блоков в каждом пуле, это может быть относительно медленным.
Идея здесь состоит в том, чтобы избежать обеих этих возможностей. В типичном случае ваши распределения/деаллокация в любом случае более или менее привязаны к стеку, и когда они являются размером, который вы выделяете, скорее всего, будут в локальной переменной. Когда вы освободитесь, вы, как правило, находитесь на (или, по крайней мере, близком) к тому же уровню стека, где и выполняете выделение, так что одна и та же локальная переменная будет легко доступна и, вероятно, не будет выгружена на диск (или что-то в этом роде), так как другие переменные, хранящиеся поблизости, также используются. Для формы без массива вызов ::operator new
будет происходить, как правило, из new expression
, а звонок - ::operator delete
из соответствия delete expression
.В этом случае код, созданный для создания/уничтожения объекта, «знает» размер, который он будет запрашивать (и уничтожать), основываясь исключительно на типе создаваемого/уничтожаемого объекта.
Re: версия массива: это проблема компилятора, а не ваша (вы передаете ей все, что было передано 'operator new []', чтобы выделить эту память). –
Dosen't эта фраза из статьи * Современные распределители памяти часто выделяют в категориях размеров и, по соображениям экономии пространства, не сохраняют размер объекта рядом с объектом. Затем Deallocation требует поиска для хранилища категорий размера, содержащего объект. Этот поиск может быть дорогостоящим, особенно в том случае, когда структуры данных поиска часто не хранятся в кэшах памяти. * Закройте то, что вы спрашиваете? –
@ T.C. Но как я могу узнать, что было передано 'operator new []'? Это просто 'sizeof arr'? – vsoftco