"premature"可能销毁吗?
Is "premature" destruction possible?
result_t work(resource_t& resource) {
lock_t ___(resource);
return work_impl(resource);
}
是否保证___
的析构函数在返回work_impl()
后将调用?还是编译器可以在调用work_impl()
之前自由销毁___
?
表达式work_impl(resource)
将被执行,结果将被复制到调用方或用作临时。然后,对象___
将被销毁。
另一方面,不要使用 __
或 ___
作为任何标识符的前缀。它们保留给编译器。
如果析构函数是非平凡的,则可能不会调用它过早,前提是代码的其余部分是正确的。 在未定义行为的情况(例如,具有两个或更相邻的_
),当然,没有保证。
如果无法区分,编译器可以自由地做任何它喜欢的事情。但是,如果析构函数具有某些程序可见的效果,则它总是会在work_impl
返回后发生。
该程序的行为实际上是未定义的,标识符__
是保留的,我们可以从草案中看到C++标准17.6.4.3
保留名称第 2 段说:
如果程序在保留它的上下文中声明或定义名称,则此子句明确允许的名称除外,则其行为是未定义的。
如果我们进一步查看17.6.4.3.2
全球名称部分,其中说:
包含双下划线 _ _ 或以下划线后跟大写字母 (2.12) 开头的每个名称都保留给实现以供任何使用。
因此,除非编译器文档__
可供用户代码免费使用,否则它将被保留。
隐式调用析构函数
因此,如果该程序没有调用未定义的行为,则隐式调用的析构函数的规则可以从Destructotrs第11段12.4
标准草案部分获取,该部分说(强调我的)
— 对于程序终止时具有静态存储持续时间 (3.7.1) 的构造对象 (3.6.3),
— 对于线程退出时线程存储持续时间为 (3.7.2) 的构造对象,
— 对于具有自动存储持续时间 (3.7.3) 的构造对象,当创建对象的块退出 (6.7) 时,
— 对于临时对象生存期结束时构造的临时对象 (12.2),
所以这意味着当你退出work()
时,将自动对象的析构函数将被调用,这必须在返回结果后发生。我们可以进一步看到,对象的销毁顺序也从 6.6
Jump 语句中指定:
退出作用域时(无论如何完成),在该作用域中构造的具有自动存储持续时间 (3.7.3) 的对象将按其构造的相反顺序销毁。[ 注:对于临时人员,请参见 12.2。 —尾注 ]
请注意,包含双下划线__
或以下划线后跟大写字母开头的名称在任何范围内都是保留的。