“过早”的破坏是否可能?

时间:2013-11-05 14:01:52

标签: c++ destructor raii object-lifetime

result_t work(resource_t& resource) {
    lock_t ___(resource);

    return work_impl(resource);
}

是否保证___的析构函数会在work_impl()返回后被调用?或者编译器在调用___之前可以自由地销毁work_impl()吗?

4 个答案:

答案 0 :(得分:4)

将执行表达式work_impl(resource),结果将被复制到调用者端或用作临时。然后,对象___将被破坏。

另一方面,请勿使用_____作为任何标识符的前缀。它们是为编译器保留的。

答案 1 :(得分:2)

如果析构函数是非平凡的,则可能无法调用它 过早地,只要其余代码是正确的。在 未定义行为的情况(例如,带有两个或的变量名称) 更接近_),当然,没有任何保证。

答案 2 :(得分:1)

如果没有办法区分,编译器可以自由地做任何事情。但是如果析构函数具有一些程序可见的效果,它将始终在work_impl返回后发生。

答案 3 :(得分:1)

此程序的行为实际上是未定义标识符 __保留,我们可以从草案C ++中看到标准17.6.4.3 保留名称 2 说:

  

如果程序在保留它的上下文中声明或定义名称,除了本条款明确允许的名称外,其行为是未定义的。

如果我们进一步查看17.6.4.3.2 部分部分,请说明:

  

包含双下划线_ _或以下划线后跟大写字母(2.12)开头的每个名称都保留给实现以供任何使用。

因此,除非编译器文档__可由用户代码免费使用,否则保留

  

隐式调用析构函数

因此,如果此程序未调用undefined behavior,那么隐式调用的析构函数的规则可以从标准草案部分12.4 Destructotrs 段 11 表示(强调我的

  
    

- 对于在程序终止时具有静态存储持续时间(3.7.1)的构造对象(3.6.3),

         

- 对于在线程退出处具有线程存储持续时间(3.7.2)的构造对象,

         

- 对于具有自动存储持续时间(3.7.3)的构造对象,当创建对象的块退出时(6.7)

         

- 对于临时对象的生命周期结束时构造的临时对象(12.2),

  

这意味着退出work()时将调用自动对象的析构函数,这必须在返回结果后发生。我们可以进一步看到,对象的销毁顺序也是从6.6 跳转语句中指定的

  

退出范围(无论多么已完成)时,在该范围内构建的具有自动存储持续时间(3.7.3)的对象将按其构造的相反顺序销毁。 [注:对于临时学生,见12.2。 - 后注]

请注意,包含双下划线__的名称,或以下划线后跟大写字母开头的名称为reserved in any scope