В настоящее время я выделяю свою память для массивов с использованием MS_malloc. Я выравниваю память, так как я занимаюсь математикой с большой нагрузкой, и векторизация использует преимущество выравнивания. Мне было интересно, знает ли кто-нибудь, как перегружать нового оператора, чтобы сделать то же самое, поскольку я чувствую себя грязным malloc'ing всюду (и в конечном итоге хотел бы также скомпилировать на Linux)? Спасибо за любую помощьвозвращает выровненную память с новым?
ответ
Прежде всего, важно отметить, что new
и delete
могут быть перегружены либо глобально, либо только для одного класса. Оба случая показаны в this article. Также важно отметить, что если вы перегрузите new
, вы почти наверняка также захотите перегрузить delete
.
Есть несколько важных замечаний о operator new
и operator delete
:
- Стандарт C++ требует, чтобы действующий указатель возвращается, даже если размер ей передается 0.
- Там также
operator new[]
иoperator delete[]
, поэтому не забывайте перегружать их. - Производные классы наследуют
operator new
и его братьев, поэтому не забудьте их переопределить.
В Эффективное C++, пункт 8, Скотт Мейерс включает некоторые примеры pseudocodish:
void * operator new(size_t size) // your operator new might
{ // take additional params
if (size == 0) { // handle 0-byte requests
size = 1; // by treating them as
} // 1-byte requests
while (1) {
attempt to allocate size bytes;
if (the allocation was successful)
return (a pointer to the memory);
// allocation was unsuccessful; find out what the
// current error-handling function is (see Item 7)
new_handler globalHandler = set_new_handler(0);
set_new_handler(globalHandler);
if (globalHandler) (*globalHandler)();
else throw std::bad_alloc();
}
}
void operator delete(void *rawMemory)
{
if (rawMemory == 0) return; // do nothing if the null
// pointer is being deleted
deallocate the memory pointed to by rawMemory;
return;
}
Для получения дополнительной информации, я бы определенно подобрать Эффективное использование C++.
new
требуется для возврата pointer [...] suitably aligned so that it can be converted to a pointer of any complete object type
(§3.7.3.1 стандарта).
FWIW, C++ 0x добавит alignof
, в котором будет указано выравнивание, необходимое для определенного типа.
К сожалению, по какой-то причине я никогда не понимал, компиляторы обычно не применяют это правило для 128-битных SIMD-типов. Я считаю, что они все еще «новые» с 8-байтовым выравниванием. – jalf
@jalf: две причины: (1) чем больше выровненных распределений, тем выше накладные расходы на блок. Если вы сделаете много 17-байтных распределений, вы увидите разницу между их 16-юстировками и только их 4-ю выравнивание. (2) (специфичный для GNU), glibc делает меньше допущений для платформы, чем GCC, и не знает и не заботится о том, какой самый большой тип может поддерживать какой-то компилятор в системе. Но GCC «хочет» передать malloc прямо на glibc, а не добавить свой собственный механизм выравнивания, причем еще больше накладных расходов, чем malloc. Я где-то читал интересный публичный аргумент. –
...наконец, компилятор мог бы в теории выбрать просто выравнивание вызовов на «новый SIMD_Type», избегая накладных расходов при всех распределениях более 15 байт. Но это все равно будет ошибкой, потому что если вы это сделаете, вам также следует выровнять вызовы с 'new char [sizeof (SIMD_Type)]'. Консенсус заключается в том, чтобы притворяться, что SIMD-типы не являются «правильными встроенными типами», это специальные вещи, которые должны быть выделены специально. –
- 1. Как выделить 4k выровненную память
- 2. Аллокатор, который выделяет 32-байтную выровненную память
- 3. Удалить выровненную память из другого потока
- 4. Как выделить и освободить выровненную память в C
- 5. Как инициализировать память новым оператором в C++?
- 6. Удалит команду очистить память, выделенную новым?
- 7. Память выделяет и возвращает
- 8. C++ конструктор с новым
- 9. Щебет вырезать выровненную строчку снизу
- 10. Как реализовать выровненную систему отладки?
- 11. Malloc не возвращает память, почему?
- 12. DOMPDF: Генерировать одинаково выровненную таблицу
- 13. Какова цель стандартного требования C++, что новый char [] дает выровненную память?
- 14. Действительно ли новый символ фактически гарантирует выровненную память для типа класса?
- 15. Как получить выровненную по страницам память от оператора new или malloc для mremap
- 16. Как освободить память, используемую новым классом, чтобы избежать утечки памяти?
- 17. Можно ли «удалить» память, выделенную «новым [1]» и наоборот?
- 18. Как правильно освободить память, выделенную местом размещения, новым?
- 19. sizeWithAttributes Возвращает неправильный размер с новым символом строки \ n
- 20. FakeItEasy - проблемы с новым модификатором
- 21. Использование оператора = в сочетании с новым оператором
- 22. В Win32 HeapFree не возвращает память
- 23. Как сделать навигационную марку, выровненную по центру
- 24. Программа Java libgdx не возвращает выделенную память
- 25. Realloc() возвращает NULL, когда память доступна
- 26. Как получить табличную ячейку, выровненную вправо?
- 27. Process.PrivateMemorySize64 возвращает память, а не частное
- 28. malloc возвращает указатель на выделенную память
- 29. Почему автовакуумный процесс не возвращает память
- 30. UICollectionView Как реализовать горизонтальную выровненную прокрутку
Итак, могу ли я просто поместить это в заголовок и ссылаться на этот заголовок во всех моих файлах? – Steve
Ну, вы бы поместили определения в исходный файл, но да. – rlbond
просто небольшая сноска: вы также можете определить 'operator new (size_t count, size_t alignment)', чтобы вы могли явно передать выравнивание в качестве аргумента для оператора new. Это можно было бы назвать «new (alignment) AlignedType» – user666412