#c++ #память #sof
Есть ли разница в объявлении operator delete(void*) и operator delete(void*, size_t) для класса? Нужен ли на самом деле второй параметр? И если да, то зачем?
Ответы
Ответ 1
Наличие второго опционального параметра типа size_t в функции operator delete тянется еще со времен "классического" C++, т.е. C++98, где такой параметр мог использоваться в operator delete, перегруженных именно для индивидуальных классов. То есть внутри конкретного класса вы можете на выбор объявлять operator delete(void *p); // или operator delete(void *p, size_t s); В ситуации, когда удаляемый класс предоставляет свой собственный перегруженный operator delete со вторым параметром типа size_t, компилятор обязан передать в такой оператор корректный размер удаляемого блока памяти, т.е. тот же размер, что передавался в operator new при выделении этого блока. Для глобального operator delete такой возможности не предоставлялось. Эта возможность предусмотрена в языке из-за того, что перегруженные operator new и operator delete базового класса могут использоваться для выделения/освобождения памяти для объектов производных классов struct Base { void *operator new(size_t s) { std::cout << "new " << s << std::endl; return ::operator new(s); } void operator delete(void *p, size_t s) { std::cout << "delete " << s << std::endl; ::operator delete(p); } }; struct Derived : Base { char buffer[1024]; }; int main() { Base *pb = new Base; delete pb; Derived *pd = new Derived; delete pd; } При помощи анализа передаваемого в operator new и operator delete значения эти операторы могут определять, какой из возможных размеров выделяется или освобождается и соответствующим образом перенаправлять вызовы. Для глобальных функций ::operator new и ::operator delete такой возможности в C++98 не было, т.е. глобально предоставлялся только замещаемый operator delete(void *p); Однако начиная с С++14 такая возможность была предоставлена и для глобальных функций тоже. Это было сделано для улучшения поддержки аллокаторов, которые не хранят размер блока в самом блоке (или где-то рядом), т.е. для аллокаторов которым трудно определить размер блока по указателю. Например, для пулов одноразмерных объектов. Также такая возможность может быть полезна для оптимизации выделения/освобождения памяти в появившейся в C++14 возможности расширенных выделений памяти, когда два или более соседних new-выражения обходятся одним вызовом operator new с суммарным размером (и, соответственно, симметричной обработкой delete-выражений). То есть если вы по какой-то причине хотите получать в ::operator delete тот же самый размер, что передавался в соответствующий вызов ::operator new, то объявляйте свой ::operator delete со вторым параметром типа size_t. Если вас не интересует этот размер, то объявляйте его без такого параметра. Ситуация с наличием сразу двух вариантов operator delete, похоже, находится в подвешенном состоянии уже давно и является дефектом стандарта. Скорее всего дело закончится тем, что предоставление сразу двух вариантов будет приводить к ошибке неоднозначности.Ответ 2
Оператор вызывается, если программист хочет вручную заниматься выделением памяти где-нибудь. (скрытно/в файлах/с обнулением) При вызове удаления объекта будет вызываться пользовательский delete с аргументом размера памяти. // > g++-5 -Wall -Wpedantic -std=c++14 operdelet.cpp # include# include class A{ int i[10]; public: void operator delete[](void * p,size_t s){ std::cout<<"A:s="<
Комментариев нет:
Отправить комментарий