Зачем новому выражению [] вызывать деструктор?

Из стандарта С++ 17 (черновик здесь) [expr.new]:

Если новое выражение создает объект или массив объектов типа класса, доступ и управление неоднозначностью выполняются для функции выделения, функции освобождения и конструктора. Если new-выражение создает массив объектов типа класса, деструктор потенциально вызывается.

Почему new[] вызывает деструктор? Это новое, в конце концов. Это не удалить.

Ответ 1

Если создание какого-либо объекта в буфере вызывает исключение, ранее созданные объекты должны быть уничтожены. Это требует доступного деструктора.

Ответ 2

Вы не учли слово "потенциально" в цитате, которую вы упомянули в стандарте.
Это означает, что существует вероятность того, что вызов деструктора может произойти. И это произойдет, если при построении какого-либо объекта в массиве возникнет исключение.

В сочетании со следующей цитатой из [class.dtor]/12.4 которой упоминается [expr.new], это становится понятным.

В каждом случае контекст вызова - это контекст построения объекта. Деструктор также вызывается неявно через использование выражения удаления для созданного объекта, выделенного новым выражением; контекст вызова - выражение удаления. [Примечание: Массив типа класса содержит несколько подобъектов, для каждого из которых вызывается деструктор. - примечание конца] Деструктор также может быть вызван явно. Деструктор потенциально вызывается, если он вызывается или как указано в [expr.new], [class.base.init] и [except.throw]. Программа плохо сформирована, если потенциально вызываемый деструктор удален или недоступен из контекста вызова.

Ответ 3

В бою:

#include <iostream>

int counter;

class Destruct
{
public:
    Destruct()
    {
        if (counter++ > 5)
            throw counter;
    }

    ~Destruct()
    {
        std::cout << "Dtor called\n";
    }
};

int main()
{
    try
    {
        new Destruct[10];
    }
    catch (...){}
}

Вы увидите что-то вроде:

Dtor called
Dtor called
Dtor called
Dtor called
Dtor called
Dtor called