Во-первых, пример:
#include <cstddef>
#include <iostream>
struct S
{
S(int i) { if(i > 42) throw "up"; }
static void* operator new(std::size_t s, int i, double d, char c)
{
std::cout << "allocated with arguments: "
<<i<<", "<<d<<", "<<c<<std::endl;
return new char[s];
}
static void operator delete(void* p, int i, double d, char c)
{
std::cout << "deallocated with arguments: "
<<i<<", "<<d<<", "<<c<<std::endl;
delete[] (char*)p;
}
static void operator delete(void* p)
{
std::cout << "deallocated w/o arguments"<<std::endl;
delete[] (char*)p;
}
};
int main()
{
auto p0 = new(1, 2.0, '3') S(42);
S* p1 = nullptr;
try
{
p1 = new(4, 5.0, '6') S(43);
}catch(const char* msg)
{
std::cout << "exception: "<<msg<<std::endl;
}
delete p1;
delete p0;
}
Выход:
allocated with arguments: 1, 2, 3
allocated with arguments: 4, 5, 6
deallocated with arguments: 4, 5, 6
exception: up
deallocated w/o arguments
Каноническое определение новой перегрузки оператора: void *operator new(std::size_t, heap h)
Я не понимаю, насколько это канонично, поскольку это не разрешено: Хорошо, теперь это допустимая форма размещения new
:)
[basic.stc.dynamic.allocation]/1
Функция распределения должна быть функцией-членом класса или глобальной функцией; программа неправильно сформирована, если функция распределения объявлена в области пространства имен, отличной от глобальной области видимости, или объявлена статической в глобальной области видимости. Тип возвращаемого значения должен быть void*
. Первый параметр должен иметь тип std::size_t
. Первый параметр не должен иметь ассоциированного аргумента по умолчанию. Значение первого параметра должно интерпретироваться как запрошенный размер выделения.
[выделено мной]
Вы можете перегрузить функцию распределения для вызова формы размещения new
, см. [expr.new] (это явно не разрешено в [basic.stc.dynamic.allocation] для нешаблонных функций, но также и не запрещено). Размещение, указанное в new(placement)
, здесь обобщается до списка-выражений. Каждое выражение в списке-выражений для определенного нового-выражения передается в качестве дополнительных аргументов функции распределения. Если вызывается функция освобождения (например, из-за того, что вызываемый ctor выдает исключение), те же аргументы плюс начальный void*
(возвращаемое значение функции распределения) передаются функции освобождения.
[expr.new]/18 гласит:
Если какая-либо часть описанной выше инициализации объекта завершается выдачей исключения, для объекта получено хранилище и может быть найдена подходящая функция освобождения, функция освобождения вызывается для освобождения памяти, в которой создавался объект, после которое исключение продолжает распространяться в контексте нового выражения. Если не удается найти однозначно подходящую функцию освобождения, распространение исключения не приводит к освобождению памяти объекта. [Примечание. Это уместно, когда вызываемая функция выделения не выделяет память; в противном случае это может привести к утечке памяти. — конец примечания ]
и /21
Если новое выражение вызывает функцию освобождения, оно передает значение, возвращенное вызовом функции распределения, в качестве первого аргумента типа void*
. Если вызывается функция освобождения места размещения, ей передаются те же дополнительные аргументы, которые были переданы функции распределения места размещения, т. е. те же аргументы, что указаны в синтаксисе нового размещения.
и /20
Объявление функции освобождения мест размещения соответствует объявлению функции распределения мест размещения, если оно имеет одинаковое количество параметров и после преобразования параметров все типы параметров, кроме первого, идентичны. Любая функция освобождения без размещения соответствует функции распределения без размещения. Если поиск находит единственную подходящую функцию освобождения, эта функция будет вызвана; в противном случае функция освобождения не будет вызываться. Если поиск находит двухпараметрическую форму обычной функции освобождения, и эта функция, рассматриваемая как функция освобождения размещения, была бы выбрана в качестве соответствия для функции распределения, программа плохо сформирована. [Пример:
struct S {
// Placement allocation function:
static void* operator new(std::size_t, std::size_t);
// Usual (non-placement) deallocation function:
static void operator delete(void*, std::size_t);
};
S* p = new (0) S; // ill-formed: non-placement deallocation function matches
// placement allocation function
— конец примера ]
Возвращаясь к [basic.stc.dynamic.deallocation]:
1 Функции освобождения должны быть функциями-членами класса или глобальными функциями; программа неправильно сформирована, если функции освобождения объявлены в области пространства имен, отличной от глобальной области видимости, или объявлены статическими в глобальной области видимости.
2 Каждая функция освобождения должна возвращать void
, а ее первый параметр должен быть void*
. Функция освобождения может иметь более одного параметра.
person
dyp
schedule
30.10.2013
new
? Размещение-новый сорт? - person John Dibling   schedule 30.10.2013