我非常有信心在程序启动时分配(并初始化,如果适用)全局声明的变量.
int globalgarbage;
unsigned int anumber = 42;
Run Code Online (Sandbox Code Playgroud)
但是在函数中定义的静态的呢?
void doSomething()
{
static bool globalish = true;
// ...
}
Run Code Online (Sandbox Code Playgroud)
globalish分配的空间是什么时候?我猜测程序什么时候开始.但是它也被初始化了吗?或者它doSomething()是在第一次调用时初始化的?
Ada*_*rce 81
我很好奇,所以我编写了以下测试程序并用g ++ 4.1.2版编译.
include <iostream>
#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;
};
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;
}
Run Code Online (Sandbox Code Playgroud)
结果不是我的预期.直到第一次调用函数时才调用静态对象的构造函数.这是输出:
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
Run Code Online (Sandbox Code Playgroud)
小智 48
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)).否则,在第一次控制通过其声明时初始化这样的对象; 这样的对象在初始化完成时被认为是初始化的.如果通过抛出异常退出初始化,则初始化未完成,因此下次控制进入声明时将再次尝试初始化.如果控件在初始化对象时重新输入声明(递归),则行为未定义.[ 例如:
Run Code Online (Sandbox Code Playgroud)int foo(int i) { static int s = foo(2*i); // recursive call - undefined return i+1; }- 结束例子 ]
五
当且仅当构造变量时,将执行具有静态存储持续时间的本地对象的析构函数.[注意: basic.start.term 描述了破坏具有静态存储持续时间的本地对象的顺序.]
Eug*_*ene 24
所有静态变量的内存在程序加载时分配.但是本地静态变量在第一次使用时创建并初始化,而不是在程序启动时初始化.还有关于一些良好的阅读,和静在一般情况下,在这里.总的来说,我认为其中一些问题取决于实现,特别是如果你想知道这些东西的位置在哪里.
Hen*_*enk 10
编译器将foo在程序加载时分配函数中定义的静态变量,但是编译器还会向函数添加一些附加指令(机器代码),foo以便在第一次调用它时,这个附加代码将初始化静态变量(例如,如果适用,调用构造函数).
@Adam:编译器在幕后注入代码是你看到的结果的原因.
我尝试再次测试来自Adam Pierce的代码并添加了两个案例:类中的静态变量和POD类型.我的编译器是g ++ 4.8.1,在Windows操作系统(MinGW-32)中.结果是类中的静态变量与全局变量一样.在进入main函数之前将调用它的构造函数.
结论(对于g ++,Windows环境):
(1):正确的状态应该是:"在调用来自同一翻译单元的任何函数之前".但是,为简单起见,如下例所示,那么它就是主要功能.
包括<iostream>
#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;
}
Run Code Online (Sandbox Code Playgroud)
结果:
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
Run Code Online (Sandbox Code Playgroud)
有人在Linux环境下测试过?
| 归档时间: |
|
| 查看次数: |
57017 次 |
| 最近记录: |