【问题标题】:why static variable is allocated when program starts but initialize later?为什么程序启动时分配静态变量但稍后初始化?
【发布时间】:2019-12-16 13:29:41
【问题描述】:

我是新来的,我看到函数中的静态变量在第一次调用函数之前已经初始化了。,但我仍然不知道为什么它不调用函数启动前的构造函数?

class Base
{
public:
    Base();
    ~Base();

private:

};

Base::Base()
{
    cout << "I'm Base" << endl;
}

Base::~Base()
{
}
int main()
{
    cout << "start program!" << endl;
    static Base b;
    return 0;
}

When are static function variables allocated?,我觉得情况跟我差不多。。 任何帮助将不胜感激^_^

【问题讨论】:

  • 从 6.7-p4 开始:“这样的变量在控件第一次通过其声明时被初始化;”
  • “我看到函数中的静态变量是在第一次调用函数之前初始化的” 你在哪里看到的?不正确!
  • stackoverflow.com/questions/3319753/…,看到这里,我觉得情况跟我差不多……
  • @CatTom 这个问题是关于 C 的,而你的问题是关于 C++ 的。不要假设两者的工作方式完全相同,它们是不同的语言。
  • @walnut 谢谢,所以对于C来说是对的,对于c++,还有其他情况吗?

标签: c++


【解决方案1】:

不完全是。静态变量在第一次遇到时被初始化,当然这不一定是在函数的开头。

【讨论】:

【解决方案2】:

具有静态存储持续时间的对象有两个初始化阶段:静态阶段和动态阶段。一些静态变量根本没有动态初始化。那些确实具有动态初始化的对象最初是静态零初始化的。

初始化的静态阶段发生在程序启动时,然后是其他任何事情。因此,内存也必须先分配。

初始化的动态阶段不能是瞬时的。动态初始化可能依赖于其他静态对象的初始化。一些对象必须在其他对象之前初始化。这就是分配后发生动态初始化的原因。

对于具有静态存储的命名空间范围变量,它们的动态初始化发生在 main 之前,或者它可能会被延迟,在这种情况下,它发生在来自同一个翻译单元的任何内容被访问或调用之前(实际上,延迟发生在涉及动态加载)。

对于静态局部变量...

函数中的静态变量在函数第一次调用之前被初始化

不完全是。它们的动态初始化总是在执行第一次到达它们时发生。那总是函数被调用之后;不是以前。例如:

void foo(bool bar)
{
    if (bar) {
        static T var;
    }
}

如果提供的参数是false,即使调用函数时var也不会被初始化。

未指定跨翻译单元的动态初始化顺序。否则,这将无法安全地依赖来自其他翻译单元的具有静态存储的对象的初始化,但是静态局部变量的“首次使用时初始化”行为是一个允许精确控制其初始化顺序的功能,使其即使跨越翻译单元边界也可以依赖它们的初始化。

【讨论】:

  • 你的意思是初始化包括内存分配?所以,动态初始化变量在执行不到的时候就无法在内存中搜索?
【解决方案3】:

我认为,根据您的 cmets,您缺少的细节是同时存在全局和局部静态变量。

全局静态变量在程序第一次加载时被初始化。编辑:显然这不是必需的行为(尽管它是最常见的) - 允许延迟初始化。请参阅@walnut 的评论。

例子:

int main()
{
    std::cout << "start program!" << std::endl;
    return 0;
}

static Base b;

输出:

I'm Base
start program!

虽然函数中的静态变量在控制第一次通过它们时被初始化。示例:

int main()
{
    std::cout << "start program!" << std::endl;
    static Base b;
    return 0;
}

输出:

start program!
I'm Base

根据@EvilTeach 的评论,我添加了第二个示例,以显示尽管有多个函数调用,但静态如何仅初始化一次。此外,添加了警卫(来自@eeerorika 的回答)以显示只有在执行实际到达变量时才会发生初始化。

void testFunc(bool test)
{
    std::cout << "testFunc called with: " << test << std::endl;
    if (test)
        static Base b;
}

int main()
{
    testFunc(false);
    testFunc(true);
    testFunc(true);
    return 0;
}

输出:

testFunc called with: 0
testFunc called with: 1
I'm Base
testFunc called with: 1

【讨论】:

  • 这在技术上是不正确的。编译器将非本地静态初始化延迟到第一次在翻译中使用非本地静态变量是符合标准的。因此,在您的第二种情况下,它实际上不必按该顺序打印,尽管我不知道是否有任何编译器在共享库之外以不同的方式执行它。
  • @EvilTeach 好建议。
  • @walnut 谢谢,我不知道。我在回答中添加了注释以阅读您的评论。
猜你喜欢
  • 2023-01-30
  • 2017-12-07
  • 2012-02-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-04-10
  • 2023-03-22
相关资源
最近更新 更多