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

问题描述 投票:39回答:3

从C ++ 17标准(草案here),[expr.new]:

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

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

c++ c++17 new-operator
3个回答
56
投票

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


13
投票

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

结合[class.dtor]/12.4提到[expr.new]的以下引用,这一点变得清晰起来。

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


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
© www.soinside.com 2019 - 2024. All rights reserved.