2016-07-31 2 views
0

Я слышал, что std :: vector хорош, потому что он гарантирует непрерывную выделенную память (с учетом кэша). Тогда как насчет последовательного «нового» оператора?Выполняет ли последовательные «новые» операторы смежную выделенную память?

{ 
    new Test1(); 
    new Test2(); 
    new Test3(); 
} 

Не делает ли он непрерывную выделенную память на куче?

ответ

3

Последовательные выражения new не обязательно выделяют последовательные блоки памяти.

Но C++ 14 имеет особую поддержку для такой последовательности выражений new, где при определенных условиях их можно заменить одним выражением new (которое обязательно выделяет достаточно большой кусок смежной памяти) и где соответствующий delete выражения заменяются одним выражением delete.

C++ 14 (проект N3936) §5.3.4/10:

Реализация разрешается опускать вызов сменной глобальной функции распределения (18.6.1.1, 18.6.1.2). Когда это делается, хранилище вместо этого обеспечивается реализацией или обеспечивается путем расширения выделения другого выражения new. Реализация может расширить выделение в new -expression e1 обеспечить хранение в течение new -expression e2, если следующее было бы верно, было распределение не распространяется:
- оценка e1 секвенировали до оценки e2 и
- e2 вычисляется всякий раз, когда e1 получает хранение и
- как e1 и e2 вызывать ту же сменную глобальную функцию распределения, а
- если функция распределения вызывается e1 и e2 бросает, любой exceptio нс выброшенный в оценке либо e1 или e2 будет первым пойманным в том же обработчике, и
- значения указателя, производимые e1 и e2 являются операндами к оцениваемому delete -expressions и
- оценка e2 секвенирует перед тем оценка выражения delete, операндом которого является значение указателя, созданное e1.

0

Управление памятью действительно до операционной системы - во время выполнения, это эквивалентно вызову функции C malloc несколько раз подряд, то есть смежный распределение не гарантируется (хотя, скорее всего). Чтобы гарантировать сохранение объектов в непрерывном блоке памяти, они должны храниться в массиве.

Я не уверен, какое приложение вы собираетесь использовать, но в большинстве случаев ускорение от удобства кеширования намного перевешивается накладными расходами на обход объектов. кэш-совместимость только ускоряет работу программ, работающих на больших базах данных (например, mergesort длинного массива), потому что ЦП не нуждается в перетасовке массива в и из кэша быстро - однако для небольшого количества объектов вы не используете, t нужно беспокоиться о кеше, потому что его эффект будет таким крошечным. Если вы объявляете каждый вектор в отдельности, а не как блок в массиве, я предполагаю, что их не так много, поэтому их размещение в массиве не требуется и не ускорит вашу программу.

0

В большинстве реализаций распределитель удерживал ранее свободную память, вы не ожидали, что всегда будете иметь непрерывную память.

Подумайте об этом случае: Test1 - большой объект, Test2 маленький, Test3 - средний размер.

Когда вы выделяете для Test1, текущий пул памяти не имеет достаточно большой многоразовой памяти, поэтому он запрашивает расширение кучи и выделение оттуда. Затем вы делаете для маленького Test2, это всего лишь крошечный объект, из которого ранее можно было использовать многократно используемую память, поэтому вы получаете Test2 из этого пула.

Для Test3 его аналогично Test2, но для выполнения аллокатор будет держать несколько бассейн для различного размерного диапазона, так Test3 не может идти после Test2.

ПРИМЕЧАНИЕ. Все эти требования не являются обязательными в спецификации, это зависит от реализации, и предлагаемая здесь только одна из обычной реализации (дальнейшее чтение: распределение памяти Buddy).

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