Зачем новому выражению [] вызывать деструктор? - PullRequest
39 голосов
/ 22 марта 2019

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

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

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

Ответы [ 3 ]

56 голосов
/ 22 марта 2019

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

13 голосов
/ 23 марта 2019

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

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

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

8 голосов
/ 28 марта 2019

В действии:

#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
...