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

thb*_*thb 39 c++ new-operator c++17

根据C ++ 17标准(此处为草案),[expr.new]:

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

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

Sto*_*ica 56

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


P.W*_*P.W 13

您没有在标准中提到的报价中考虑“潜在”一词。
这意味着有可能发生析构函数的调用。而且它会发生,如果阵列中的任何物体的建设将引发异常。

具有以下引自相结合[class.dtor]/12.4,其中提到[expr.new],这变得清晰。

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


Aja*_*jay 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 (...){}
}
Run Code Online (Sandbox Code Playgroud)

您将看到类似以下的输出:

Dtor called
Dtor called
Dtor called
Dtor called
Dtor called
Dtor called
Run Code Online (Sandbox Code Playgroud)