析构函数可以递归吗? [英] Can a destructor be recursive?

查看:148
本文介绍了析构函数可以递归吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

此程序是否定义明确,如果不是,则为什么要精确定义?

Is this program well-defined, and if not, why exactly?

#include <iostream>
#include <new>
struct X {
    int cnt;
    X (int i) : cnt(i) {}
    ~X() {  
            std::cout << "destructor called, cnt=" << cnt << std::endl;
            if ( cnt-- > 0 )
                this->X::~X(); // explicit recursive call to dtor
    }
};
int main()
{   
    char* buf = new char[sizeof(X)];
    X* p = new(buf) X(7);
    p->X::~X();  // explicit call to dtor
    delete[] buf;
}

我的理由:尽管两次调用析构函数是未定义的行为,每12.4 / 14 ,它的确切含义是:

My reasoning: although invoking a destructor twice is undefined behavior, per 12.4/14, what it says exactly is this:


如果为对象
调用
析构函数,则行为未定义生命周期已结束

the behavior is undefined if the destructor is invoked for an object whose lifetime has ended

似乎并没有禁止递归调用。在执行对象的析构函数时,对象的生存期尚未结束,因此再次调用该析构函数不是UB。另一方面,12.4 / 6表示:

Which does not seem to prohibit recursive calls. While the destructor for an object is executing, the object's lifetime has not yet ended, thus it's not UB to invoke the destructor again. On the other hand, 12.4/6 says:


在执行主体之后,为类X使用
析构函数称为X的直接成员的
析构函数,
称为X的直接基础
类的析构函数[...]

After executing the body [...] a destructor for class X calls the destructors for X's direct members, the destructors for X's direct base classes [...]

意味着从递归调用析构函数返回后,将调用所有成员和基类析构函数,并且在返回上一级递归时再次调用它们将是UB。因此,没有基础并且只有POD成员的类可以具有没有UB的递归析构函数。

which means that after the return from a recursive invocation of a destructor, all member and base class destructors will have been called, and calling them again when returning to the previous level of recursion would be UB. Therefore, a class with no base and only POD members can have a recursive destructor without UB. Am I right?

推荐答案

答案是否定的,因为生命周期的定义在§3.8/ 1中:

The answer is no, because of the definition of "lifetime" in §3.8/1:


T 类型的对象的生存期在以下时间结束:

The lifetime of an object of type T ends when:

-如果 T 是具有非平凡析构函数的类类型(12.4),则析构函数调用开始,或者

— if T is a class type with a non-trivial destructor (12.4), the destructor call starts, or

-对象占用的存储空间被重用或释放。

— the storage which the object occupies is reused or released.

在第一次调用析构函数时,对象的生存期已结束。因此,如果您从析构函数内部调用该对象的析构函数,则根据§12.4/ 6,该行为是未定义的:

As soon as the destructor is called (the first time), the lifetime of the object has ended. Thus, if you call the destructor for the object from within the destructor, the behavior is undefined, per §12.4/6:


如果该行为未定义,对于寿命已结束的对象调用析构函数

the behavior is undefined if the destructor is invoked for an object whose lifetime has ended

这篇关于析构函数可以递归吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆