程序退出期间的函数局部静态初始化

如何解决程序退出期间的函数局部静态初始化

标准对程序退出期间函数局部静态初始化有什么看法? 编辑:为了清楚起见,我的意思是在代码示例中的情况 - 本地静态 b 是在构造另一个静态 a 之后构造的(因此,应该先销毁 b a),但是 b 也是在 a 的析构函数中构造的,所以它应该立即销毁吗?后? UB?

我没有找到任何关于此事的参考。

我想知道这种情况是否属于 UB,或者它是否应该具有某种定义的行为?

下面的代码就是一个例子:

struct B{};

void foo()
{
    static B b;
}

struct A
{
    ~A() { foo(); }
};

int main()
{
    static A a;
    
    return 0;
}

如你所见,A的析构函数会在程序退出时发生(因为它有静态存储),它会尝试构造一个B静态实例。

我对 C++17 更感兴趣,如果它在这主题上有什么不同的话。

解决方法

鉴于 foo() 仅从 A 的析构函数中调用,因此我看不出这里有冲突。

来自[stmt.dcl]/5 [强调我的]:

具有静态或线程存储持续时间的块范围对象将被销毁当且仅当它被构造时。 [注意:[basic.start.term]描述了块范围的顺序具有静态和线程存储持续时间的对象被销毁。 — 尾注 ]

而且,来自[basic.start.term]/4 [重点我的]:

如果函数包含静态或线程存储持续时间的块范围对象,该对象已被销毁,并且在销毁具有静态或线程存储持续时间的对象期间调用该函数 /strong>,如果控制流通过先前销毁的块范围对象的定义,则程序具有未定义的行为。同样,如果块范围对象在其销毁后被间接使用(即通过指针),则行为未定义。

由于 b 中的 foo()(在这个特定示例中)直到 a 中的 main() 被销毁时才会被构造,[basic.start.term]/4 将不得违反,因为此时 b 尚未销毁。

如果在销毁 foo() 中的 a 之前调用 main(),情况就不同了。

,

由于对象 B 是由 A 的析构函数创建的,所以它会在程序退出之前被销毁。我在您的代码中添加了打印语句,使其看起来像这样:

#include <iostream>

struct B
{
    ~B()
    {
        std::cout << "Called B's Destructor...!";
    }
};

void foo()
{
    static B b;
}

struct A
{
    ~A() {
        foo();
        std::cout << "Called A's Destructor...!\n";
    }
};

int main()
{
    static A a;
    
    return 0;
}

它打印以下内容:

Called A's Destructor...!
Called B's Destructor...!

底线是,静态变量将在程序结束时(本地或全局)销毁,并按照创建的顺序进行。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?
Java在半透明框架/面板/组件上重新绘画。
Java“ Class.forName()”和“ Class.forName()。newInstance()”之间有什么区别?
在此环境中不提供编译器。也许是在JRE而不是JDK上运行?
Java用相同的方法在一个类中实现两个接口。哪种接口方法被覆盖?
Java 什么是Runtime.getRuntime()。totalMemory()和freeMemory()?
java.library.path中的java.lang.UnsatisfiedLinkError否*****。dll
JavaFX“位置是必需的。” 即使在同一包装中
Java 导入两个具有相同名称的类。怎么处理?
Java 是否应该在HttpServletResponse.getOutputStream()/。getWriter()上调用.close()?
Java RegEx元字符(。)和普通点?