什么是c或c ++中的静态块?

我想通过一个例子知道c或c ++中的静态块是什么? 我知道什么是静态但静态和静态块有什么区别?

另一种选择是您可能正在寻找Java中静态块的类比。 加载应用程序时运行的代码块。 在C ++中没有这样的东西,但它可以通过使用静态对象的构造函数来伪造。

foo.cpp: struct StaticBlock { StaticBlock(){ cout << "hello" << endl; } } static StaticBlock staticBlock; void main(int, char * args[]){ } 

然而。 之前我一直被它咬过,因为它是C ++标准的一个微妙优势。 如果main调用的任何代码都无法访问静态对象,则静态对象的构造函数可能会被调用,也可能不会被调用。

我发现使用gcc hello将获得输出,而使用visual studio则不会。

我在The Code Project上找到了这个答案。 它涉及一个额外的静态变量,但我相信它比bradgonesurfing的答案更可靠。 基本上,就是这样:

 class Foo { public: static int __st_init; private: static int static_init(){ /* do whatever is needed at static init time */ return 42; } }; int Foo::__st_init = Foo::static_init(); 

这也意味着,就像Java的静态块一样,你不需要实际拥有class Foo的实例,这在类可以占用大量数据时很有用,而你只需要在加载之前自动调用某些东西,而不是实例化一个额外的实例。 您可以测试该确切的代码块。 我只是编译它(使用static_init()的一点输出,并且main()打印Foo :: __ st_init,只是为了确保),它工作得很好。

 $g++ -v Using built-in specs. COLLECT_GCC=g++ COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/4.6.1/lto-wrapper Target: x86_64-linux-gnu Configured with: ../src/configure -v --with-pkgversion='Ubuntu/Linaro 4.6.1-9ubuntu3' --with-bugurl=file:///usr/share/doc/gcc-4.6/README.Bugs --enable-languages=c,c++,fortran,objc,obj-c++,go --prefix=/usr --program-suffix=-4.6 --enable-shared --enable-linker-build-id --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.6 --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --enable-plugin --enable-objc-gc --disable-werror --with-arch-32=i686 --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu Thread model: posix gcc version 4.6.1 (Ubuntu/Linaro 4.6.1-9ubuntu3) 

编辑:

对不起,这太晚了,但我测试了bradgonesurfing提到的:

如果你测试它我访问main中的变量“只是为了确保”你确保变量是可达的,因此变量将被初始化,因此将调用static_init。 如果你不打印Foo :: __ st_init,你确定它会执行吗?

我在main.cpp中使用了以下内容:

 #include  using namespace std; class Foo { public: static int __st_init; private: static int static_init(){ /* do whatever is needed at static init time */ cout << "Hello, World!"; return 42; } }; int Foo::__st_init = Foo::static_init(); int main(int argc, char** argv) { return 0; } 

我用g++ ./main.cpp -o main编译并运行它并收到一个友好的“Hello,World!” 我的控制台上的消息。 为了彻底,我也编译了相同的版本但没有打印并使用g++ ./main.cpp -g -o main编译。 然后我用gdb运行可执行文件并得到以下结果:

 (gdb) break Foo::static_init Breakpoint 1 at 0x400740: file ./main.cpp, line 12. (gdb) start Temporary breakpoint 2 at 0x4006d8: file ./main.cpp, line 19. Starting program: /home/caleb/Development/test/main-c++ Breakpoint 1, Foo::static_init () at ./main.cpp:12 12 return 42; (gdb) 

这是g ++的更新版本输出: g++ (Ubuntu 4.8.2-19ubuntu1) 4.8.2

在C / C ++中没有名称为“static block”的概念。 但是Java有一个“静态块”是一个类的初始化代码块,它在创建一个类的第一个实例之前只运行一次。 基本概念“只运行一次的东西”可以在C / C ++中使用静态变量进行模拟,例如:

 int some_function(int a, int b) { static bool once=true; if (once) { // this code path runs only once in the program's lifetime once=false; } ... } 

但这不是线程安全的 。 在有多个线程的情况下使这种工作正常运行有时会很困难和棘手。

事实上,C ++没有静态块作为语言的一部分,你可以在没有你(作为用户)必须使用任何类或命名空间的情况下实现静态块,并且可以编写:

 #include "static_block.h" static_block { int x = 1; int y = 2; int z = x+y; std::cout << z << " = " << x " << " + " << y << "\n"; } 

或者你想要的任何其他东西 但是,在文件范围内,您不能拥有类中的那些。 在我对相关问题的回答中查看这些内容的详细说明,以及static_block.h的代码。

注意:这不需要C ++ 11,并且适用于旧的编译器。

在C ++中,存在匿名命名空间的概念。

 foo.cpp: namespace { int x; int y; } 

在C中获得相同的效果

 foo.cpp: static int x; static int y; 

简单来说,当编译器声明为静态或在匿名命名空间中时,编译器不会从转换单元导出符号。