Установка ограничений на перегрузку new и delete

Можно ли наложить ограничения на операторы перегрузки new и delete? Мой перегруженный новый файл связан с моей тестовой программой в другом файле.

Сценарий такой:

if(condition is satisfied)
   call overloaded new
else
   call the actual new defined in new.h

person RajSanpui    schedule 24.02.2011    source источник
comment
Это перегрузка (то есть другая подпись и ее необходимо вызывать с новым синтаксисом размещения) или замена (то есть та же подпись, что и версия, которую вы хотите вызвать).   -  person AProgrammer    schedule 24.02.2011
comment
@STATUS_ACCESS_DENIED, я только что добавил ...   -  person AProgrammer    schedule 24.02.2011
comment
@AProgrammer: Что здесь должно делать новое размещение?   -  person RajSanpui    schedule 25.02.2011


Ответы (4)


Есть три способа предоставить оператора new.

  • замена одного или нескольких из четырех операторов по умолчанию, не связанных с размещением, новыми,

  • предоставление перегрузки оператору по умолчанию new (таким образом, с дополнительным параметром, они могут вызываться с синтаксисом размещения new),

  • предоставляя оператору новые члены класса, они будут вызываться только для этого класса и его потомка.

В последних двух случаях можно вызвать один из наиболее известных операторов new с синтаксисом:

ptr = ::operator new(sz);
ptr = ::operator new[](sz);
ptr = ::operator new(sz, std::nothrow);
ptr = ::operator new[](sz, std::nothrow);

но если вы их заменили, будет вызвана ваша замена. Вы не можете называть операторы по умолчанию новыми, которые вы заменили (ну, возможно, вы можете использовать уловки компоновщика, специфичные для реализации, но это выходит за рамки языка).

О замене оператора на новый:

  • вы должны заменить два оператора new и соответствующие два оператора delete вместе (или один из операторов удаления можно легко вызвать с помощью неожиданного указателя)
  • вы должны заменить два оператора new [] и соответствующие два оператора delete [] вместе (по той же причине)
  • Обратите внимание на то, что возможно с новыми обработчиками, некоторые библиотеки играют с этим.
person AProgrammer    schedule 25.02.2011

Всегда используйте свой перегруженный _1 _ / _ 2_ и проверяйте свое состояние внутри его реализации.

person 0xC0000022L    schedule 24.02.2011
comment
Условие можно проверить, но если оно ложное, как вернуться к исходному новому? Я имею ввиду новое в new.h? - person RajSanpui; 25.02.2011

Как только вы замените ::operator new() по умолчанию, вы больше не сможете его использовать - он ушел навсегда. См. этот вопрос.

Если вы хотите получить эффект оригинального ::operator new(), вам придется заново реализовать его, что не очень сложно.

person sharptooth    schedule 25.02.2011

Вы можете легко выполнить проверку в перегруженном новом операторе. Обязательно реализуйте все разновидности нового оператора (как уже указывал AProgrammer).

Вызвать оригинал / по умолчанию новым невозможно, но реализовать самостоятельно несложно. В конце концов, new выделяет только память, вот и все. Поэтому вместо вызова исходного / стандартного нового вы также можете вызвать malloc, HeapAlloc или любую подпрограмму выделения памяти, найденную в вашей системе. Обязательно вызовите соответствующий метод освобождения памяти (free, HeapFree, ...) в вашей реализации удаления.

Вы не сказали, какое условие вы собираетесь проверить в своей реализации new? Если это «статическое» условие (я имею в виду: всегда дает один и тот же результат во время выполнения вашего приложения), то же условие также должно быть добавлено в вашу реализацию удаления.

Если условие зависит от ситуации и изменяется во время выполнения вашего приложения, вы должны предусмотреть метод, с помощью которого вы можете узнать, какую реализацию удаления использовать в вашей функции удаления. Вот один из приемов:

В вашей реализации нового:

  • выделить на 8 байтов больше, чем запрошено (это должно быть 8 байтов для правильного выравнивания)
  • заполните первые 8 байтов идентификатором, чтобы вы могли знать, какую базовую функцию распределения памяти вы использовали
  • добавить 8 байтов к выделенному указателю и вернуть этот

В вашей реализации удаления:

  • вычтите 8 байтов из указанного вам указателя
  • проверьте идентификацию, найденную в этом месте (см. новое), чтобы увидеть, какой тип базовой реализации удаления вы должны вызвать
person Patrick    schedule 25.02.2011