【发布时间】:2019-03-22 20:32:37
【问题描述】:
来自 C++17 标准(草案here),[expr.new]:
如果 new-expression 创建了一个对象或类类型的对象数组,则对分配函数、解除分配函数和构造函数进行访问和歧义控制。 如果 new-expression 创建了一个类类型的对象数组,则可能会调用析构函数。
为什么new[] 会调用析构函数?毕竟它是新的。它不是删除。
【问题讨论】:
标签: c++ c++17 new-operator
来自 C++17 标准(草案here),[expr.new]:
如果 new-expression 创建了一个对象或类类型的对象数组,则对分配函数、解除分配函数和构造函数进行访问和歧义控制。 如果 new-expression 创建了一个类类型的对象数组,则可能会调用析构函数。
为什么new[] 会调用析构函数?毕竟它是新的。它不是删除。
【问题讨论】:
标签: c++ c++17 new-operator
如果缓冲区中任何对象的构造引发异常,则必须销毁先前构造的对象。这需要一个可用的析构函数。
【讨论】:
new 不需要可用的 d'tor。
您在引用标准时没有考虑过“潜在地”这个词。
这意味着有可能调用析构函数可能发生。如果数组中的任何对象的构造引发异常,就会发生。
结合[class.dtor]/12.4 中提到[expr.new]的以下引用,这一点变得清晰。
在每种情况下,调用的上下文都是对象构造的上下文。析构函数也通过使用删除表达式来隐式调用,用于由 new 表达式分配的构造对象;调用的上下文是删除表达式。 [ 注意:类类型的数组包含多个子对象,每个子对象都调用析构函数。 — 尾注 ] 也可以显式调用析构函数。 如果调用或在
[expr.new]、[class.base.init]和[except.throw]中指定,则可能调用析构函数。如果一个可能被调用的析构函数被删除或无法从调用上下文中访问,则该程序是格式错误的。
【讨论】:
在行动:
#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
【讨论】: