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

Abh*_*eet 10 c c++ static-block

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

bra*_*ing 30

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

foo.cpp:

struct StaticBlock {
    StaticBlock(){
        cout << "hello" << endl;
    }
}


static StaticBlock staticBlock;

void main(int, char * args[]){

}
Run Code Online (Sandbox Code Playgroud)

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

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

  • +1:此外,初始化顺序是未定义的,这也可能带来各种令人头疼的问题.我也希望看到一个可靠的静态初始化框架. (3认同)

Cal*_*994 16

我在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();
Run Code Online (Sandbox Code Playgroud)

这也意味着,就像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)
Run Code Online (Sandbox Code Playgroud)

编辑:

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

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

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

#include <iostream>

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;
}
Run Code Online (Sandbox Code Playgroud)

我编译g++ ./main.cpp -o main并运行它,并收到一个友好的"你好,世界!" 我的控制台上的消息.为了彻底,我也编译了相同的版本,但没有打印和编译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) 
Run Code Online (Sandbox Code Playgroud)

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

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

Nor*_*ame 5

在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; 
 } 
 ...
}
Run Code Online (Sandbox Code Playgroud)

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