当前位置:  开发笔记 > 编程语言 > 正文

何时分配/初始化函数级静态变量?

如何解决《何时分配/初始化函数级静态变量?》经验,为你挑选了5个好方法。

我非常有信心在程序启动时分配(并初始化,如果适用)全局声明的变量.

int globalgarbage;
unsigned int anumber = 42;

但是在函数中定义的静态的呢?

void doSomething()
{
  static bool globalish = true;
  // ...
}

globalish分配的空间是什么时候?我猜测程序什么时候开始.但是它也被初始化了吗?或者它doSomething()是在第一次调用时初始化的?



1> Adam Pierce..:

我很好奇,所以我编写了以下测试程序并用g ++ 4.1.2版编译.

include 
#include 

using namespace std;

class test
{
public:
        test(const char *name)
                : _name(name)
        {
                cout << _name << " created" << endl;
        }

        ~test()
        {
                cout << _name << " destroyed" << endl;
        }

        string _name;
};

test t("global variable");

void f()
{
        static test t("static variable");

        test t2("Local variable");

        cout << "Function executed" << endl;
}


int main()
{
        test t("local to main");

        cout << "Program start" << endl;

        f();

        cout << "Program end" << endl;
        return 0;
}

结果不是我的预期.直到第一次调用函数时才调用静态对象的构造函数.这是输出:

global variable created
local to main created
Program start
static variable created
Local variable created
Function executed
Local variable destroyed
Program end
local to main destroyed
static variable destroyed
global variable destroyed


作为澄清:静态变量在第一次执行命中它的声明时被初始化,而不是在调用包含函数时.如果你只是在函数的开头有一个静态(例如在你的例子中),这些是相同的,但不一定:例如,如果你有'if(...){static MyClass x; ...}',然后在if语句的条件求值为false的情况下,在第一次执行该函数期间,不会在ALL处初始化'x'.
但这不会导致运行时开销,因为每次使用静态变量时,程序都必须检查它是否以前使用过,如果不是,则必须初始化?在那种情况下,这种情况有点糟糕.

2> 小智..:

C++标准中的一些相关措辞:

3.6.2非本地对象的初始化[basic.start.init]

1

具有静态存储持续时间(basic.stc.static)的对象的存储应在任何其他初始化发生之前进行零初始化(dcl.init).具有使用常量表达式(expr.const)初始化的静态存储持续时间的POD类型(basic.types)的对象应在任何动态初始化发生之前初始化.具有在同一翻译单元中定义并动态初始化的静态存储持续时间的命名空间作用域的对象应按其定义出现在翻译单元中的顺序进行初始化.[注意: dcl.init.aggr 描述了聚合成员初始化的顺序.stmt.dcl中描述了本地静态对象的初始化.]

[下面的更多文本为编译器编写者添加更多自由]

6.7声明声明[stmt.dcl]

...

4

零初始化(dcl.init具有静态存储时间(所有本地对象)basic.stc.static任何其他初始化发生之前执行).具有使用常量表达式初始化的静态存储持续时间的POD类型(basic.types)的本地对象在其首次输入块之前初始化.允许实现在静态存储持续时间内执行其他本地对象的早期初始化,条件是允许实现静态初始化具有命名空间范围内的静态存储持续时间的对象(basic.start.init)).否则,在第一次控制通过其声明时初始化这样的对象; 这样的对象在初始化完成时被认为是初始化的.如果通过抛出异常退出初始化,则初始化未完成,因此下次控制进入声明时将再次尝试初始化.如果控件在初始化对象时重新输入声明(递归),则行为未定义.[ 例如:

      int foo(int i)
      {
          static int s = foo(2*i);  // recursive call - undefined
          return i+1;
      }

- 结束例子 ]

当且仅当构造变量时,将执行具有静态存储持续时间的本地对象的析构函数.[注意: basic.start.term 描述了破坏具有静态存储持续时间的本地对象的顺序.]



3> Eugene..:

所有静态变量的内存在程序加载时分配.但是本地静态变量在第一次使用时创建并初始化,而不是在程序启动时初始化.还有关于一些良好的阅读,和静在一般情况下,在这里.总的来说,我认为其中一些问题取决于实现,特别是如果你想知道这些东西的位置在哪里.


不完全是,本地静态分配并在程序加载时进行零初始化(在引号中,因为这也不完全正确),然后在第一次输入它们所在的函数时重新初始化.

4> Henk..:

编译器将foo在程序加载时分配函数中定义的静态变量,但是编译器还会向函数添加一些附加指令(机器代码),foo以便在第一次调用它时,这个附加代码将初始化静态变量(例如,如果适用,调用构造函数).

@Adam:编译器在幕后注入代码是你看到的结果的原因.



5> Thang Le..:

我尝试再次测试来自Adam Pierce的代码并添加了两个案例:类中的静态变量和POD类型.我的编译器是g ++ 4.8.1,在Windows操作系统(MinGW-32)中.结果是类中的静态变量与全局变量一样.在进入main函数之前将调用它的构造函数.

结论(对于g ++,Windows环境):

    类中的全局变量静态成员:在进入main函数(1)之前调用构造函数.

    局部静态变量:构造函数仅在第一次执行到达其声明时被调用.

    如果Local静态变量是POD类型,则在进入main函数(1)之前也会初始化它.POD类型示例:static int number = 10;

(1):正确的状态应该是:"在调用来自同一翻译单元的任何函数之前".但是,为简单起见,如下例所示,那么它就是主要功能.

包括

#include < string>

using namespace std;

class test
{
public:
   test(const char *name)
            : _name(name)
    {
            cout << _name << " created" << endl;
    }

    ~test()
    {
            cout << _name << " destroyed" << endl;
    }

    string _name;
    static test t; // static member
 };
test test::t("static in class");

test t("global variable");

void f()
{
    static  test t("static variable");
    static int num = 10 ; // POD type, init before enter main function

    test t2("Local variable");
    cout << "Function executed" << endl;
}

int main()
{
    test t("local to main");
    cout << "Program start" << endl;
    f();
    cout << "Program end" << endl;
    return 0;
 }

结果:

static in class created
global variable created
local to main created
Program start
static variable created
Local variable created
Function executed
Local variable destroyed
Program end
local to main destroyed
static variable destroyed
global variable destroyed
static in class destroyed

有人在Linux环境下测试过?

推荐阅读
郑谊099_448
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有