为什么new []表达式曾经调用析构函数?

时间:2019-03-22 20:32:38

标签: c++ c++17 new-operator

根据C ++ 17标准(草稿here),[expr.new]:

  

如果 new-expression 创建一个类类型的对象或对象数组,则将对分配函数,释放函数和构造函数进行访问和歧义控制。 如果 new-expression 创建了一个类类型的对象数组,则可能会调用析构函数。

为什么new[]会调用析构函数?毕竟是。它不是删除。

3 个答案:

答案 0 :(得分:56)

如果缓冲区中任何对象的构造引发异常,则必须销毁先前构造的对象。这需要一个可用的析构函数。

答案 1 :(得分:13)

您在标准中提到的引号中没有考虑“可能” 一词。
这意味着可能会发生析构函数的调用。如果数组中任何对象的构造引发异常,则会发生

结合以下来自[class.dtor]/12.4的引述 [expr.new] 的引言,很清楚。

  

在每种情况下,调用的上下文都是对象构造的上下文。对于由new-expression分配的构造对象,还可以通过使用delete-expression隐式调用析构函数。调用的上下文是delete-expression。 [注意: 一个类类型的数组包含多个子对象,每个子对象都调用析构函数。 -注意]也可以显式调用析构函数。 如果析构函数被调用或在[expr.new] [class.base.init][except.throw]中指定,则可能会调用它。如果潜在调用的析构函数被删除或无法从调用上下文访问,则程序格式错误。

答案 2 :(得分:8)

实际情况:

#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