关于c++的函数内static变量的初始化
看到豆瓣一个友邻的一篇博客帖子如何保证某个函数只被调用一次。帖子的评论里,大家意见纷纷。
我写了完整的代码实现作者的意图。
#include <stdio.h>
int callee()
{
printf("Callee.\n");
return 0;
}
int caller()
{
static int i = (callee(),1);
printf("Caller.\n");
return 0;
}
int main()
{
printf("Main.\n");
caller();
caller();
caller();
return 0;
}
g++编译,运行之后,输出结果是
Main
Callee
Caller
Caller
Caller
这个结果出乎我的意料,我预计的顺序应该是
Callee
Main
Caller
Caller
Caller
这之间的区别是,我预计Callee在Main之前,但是实际Callee在Main之后。
如果把static int i = (callee(),1);从caller中移出来,放在外面,则输出结果与我的预计是一致的。
看来c++把这个函数内部static变量的初始化推迟到了caller的第一次调用, 而不是像其他global变量一样,在main之前就进行它们的初始化。
这段代码只能在C++下编译成功,如果存成c文件,编译器会出错“initializer element is not constant”, 显然c编译器把这种函数内部static变量与其他全局变量一样对待,试图在compile的时候就把值写入elf文件中,也因此只支持用常数初始化全局变量。
c++真是每一个毛孔都藏着surprise的魔鬼语言。
我写了完整的代码实现作者的意图。
#include <stdio.h>
int callee()
{
printf("Callee.\n");
return 0;
}
int caller()
{
static int i = (callee(),1);
printf("Caller.\n");
return 0;
}
int main()
{
printf("Main.\n");
caller();
caller();
caller();
return 0;
}
g++编译,运行之后,输出结果是
Main
Callee
Caller
Caller
Caller
这个结果出乎我的意料,我预计的顺序应该是
Callee
Main
Caller
Caller
Caller
这之间的区别是,我预计Callee在Main之前,但是实际Callee在Main之后。
如果把static int i = (callee(),1);从caller中移出来,放在外面,则输出结果与我的预计是一致的。
看来c++把这个函数内部static变量的初始化推迟到了caller的第一次调用, 而不是像其他global变量一样,在main之前就进行它们的初始化。
这段代码只能在C++下编译成功,如果存成c文件,编译器会出错“initializer element is not constant”, 显然c编译器把这种函数内部static变量与其他全局变量一样对待,试图在compile的时候就把值写入elf文件中,也因此只支持用常数初始化全局变量。
c++真是每一个毛孔都藏着surprise的魔鬼语言。
热门话题 · · · · · · ( 去话题广场 )
- 身边的科普现场 新话题
- 维系精神生活的北京角落 864次浏览
- 现代人的“卡夫卡时刻” 1627次浏览
- 一人一杯一口入魂的夏日特饮 1.0万次浏览
- 少年时代的科普读物 新话题
- 我在网络上感受到的陌生人善意 355次浏览