代码之家  ›  专栏  ›  技术社区  ›  Abhineet

C或C++中的静态块是什么?[复制品]

  •  10
  • Abhineet  · 技术社区  · 14 年前

    我想知道,C或C++中的静态块是什么?我知道什么是静态的,但是静态块和静态块的区别是什么?

    5 回复  |  直到 7 年前
        1
  •  30
  •   bradgonesurfing    14 年前

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

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

    然而。我以前被这个东西咬过,因为它是C++的一个微妙的边缘例子。 标准。如果静态对象不能被main调用的任何代码访问, 静态对象的构造函数可以调用,也可以不调用。

    我发现使用gcc hello将得到输出,而使用Visual Studio,hello将得到输出。 不是。

        2
  •  15
  •   Community Dai    7 年前

    我发现 this 在代码项目上回答。它包含了一个额外的静态变量,但我相信它比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()print foo::u 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::\u st\u 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;
    }
    

    我编的 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) 
    

    以下是G++的当前版本输出: g++ (Ubuntu 4.8.2-19ubuntu1) 4.8.2

        3
  •  5
  •   Nordic Mainframe    14 年前

    在C/C++中没有“静态块”这个概念。但是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; 
     } 
     ...
    }
    

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

        4
  •  1
  •   Community Dai    7 年前

    实际上,C++没有作为语言的一部分的静态块, 可以 实现静态块时,您(作为用户)不必使用任何类或命名空间,并且可以写入:

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

    或者其他你想要的。但是,在类中不能只在文件范围内拥有这些。请参阅我的 answer 相关问题的代码 static_block.h here .

    注: 这不需要C++ 11,它将与旧编译器很好地工作。

        5
  •  0
  •   bradgonesurfing    14 年前

    在C++中,有一个匿名命名空间的概念。

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

    在C中得到同样的效果

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

    简单来说,编译器不会从 当它们被声明为静态或 在匿名命名空间中。

    推荐文章