15 Special member functions [special]

15.5 Free store [class.free]

Любая функция распределения для класса T является статическим членом (даже если не объявлен явно static).

[Example:

class Arena;
struct B {
  void* operator new(std::size_t, Arena*);
};
struct D1 : B {
};

Arena*  ap;
void foo(int i) {
  new (ap) D1;      // calls B​::​operator new(std​::​size_­t, Arena*)
  new D1[i];        // calls ​::​operator new[](std​::​size_­t)
  new D1;           // ill-formed: ​::​operator new(std​::​size_­t) hidden
}

end example]

Когда объект удаляется с помощью delete-expressiona, функция освобождения ( для объектов, не являющихся массивами или для массивов) вызывается (неявно) для освобождения памяти, занятой объектом ( ).operator delete() operator delete[]() [basic.stc.dynamic.deallocation]

Поиск специфичной для класса функции освобождения памяти является частью общей функции поиска ([expr.delete]) и происходит следующим образом. Если delete-expression используется для освобождения объекта класса, статический тип которого имеет виртуальный деструктор, функция освобождения - это функция, выбранная в точке определения виртуального деструктора динамического типа ([class.dtor]).118 В противном случае, если delete-expression используется для освобождения объекта класса T или его массива, статический и динамический типы объекта должны быть идентичными, а имя функции освобождения ищется в области видимости T. Если этот поиск не может найти имя,[expr.delete]продолжается поиск общей функции освобождения памяти ( ). Если результат поиска неоднозначен или недоступен, или если поиск выбирает функцию освобождения размещения, программа имеет неправильный формат.

Любая функция освобождения класса X является статическим членом (даже если не объявлена ​​явно static). [Example:

class X {
  void operator delete(void*);
  void operator delete[](void*, std::size_t);
};

class Y {
  void operator delete(void*, std::size_t);
  void operator delete[](void*);
};

end example]

Поскольку функции распределения и освобождения членов static не могут быть виртуальными. [ Однако, когда of a относится к объекту типа класса, потому что фактически вызванная функция освобождения ищется в области действия класса, который является динамическим типом объекта, если деструктор является виртуальным, эффект тот же . Например, Note: cast-expressiondelete-expression

struct B {
  virtual ~B();
  void operator delete(void*, std::size_t);
};

struct D : B {
  void operator delete(void*);
};

void f() {
  B* bp = new D;
  delete bp;        // 1: uses D​::​operator delete(void*)
}

Здесь память для объекта класса, неD являющегося массивом, освобождается D​::​operator delete()из-за виртуального деструктора. ] [ Виртуальные деструкторы не влияют на фактически вызываемую функцию освобождения, когда a ссылается на массив объектов типа класса. Например, end noteNote: cast-expressiondelete-expression

struct B {
  virtual ~B();
  void operator delete[](void*, std::size_t);
};

struct D : B {
  void operator delete[](void*, std::size_t);
};

void f(int i) {
  D* dp = new D[i];
  delete [] dp;     // uses D​::​operator delete[](void*, std​::​size_­t)
  B* bp = new D[i];
  delete[] bp;      // undefined behavior
}

end note]

Доступ к функции освобождения проверяется статически. Следовательно, даже если на самом деле может быть выполнен другой, статически видимая функция освобождения должна быть доступна. [ Example: Для вызова в строке «// 1» выше, если бы B​::​operator delete() это было так private, выражение удаления было бы неправильно сформировано. ]end example

[ Note: Если функция освобождения не имеет явного значения noexcept-specifier, она не выбрасывает exception specification. ]end note

Подобное положение не требуется для версии массива, operator delete поскольку [expr.delete] в этой ситуации требуется, чтобы статический тип удаляемого объекта был таким же, как и его динамический тип.