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

发布于 2024-09-12 06:49:20 字数 58 浏览 5 评论 0原文

我想知道什么是 C 或 C++ 中的静态块,并举例说明?我知道什么是静态,但是静态和静态块有什么区别?

I want to know that what is static block in c or c++ with an example? I know what is static but what is the difference between static and static block?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

冰之心 2024-09-19 06:49:20

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

foo.cpp:

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


static StaticBlock staticBlock;

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

}

然而。我之前就被这个问题困扰过,因为它是 C++ 的一个微妙的边缘情况
标准。如果 main 调用的任何代码都无法访问静态对象
静态对象的构造函数可能会也可能不会被调用。

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

Another alternative is that you might be looking for the analogy of a static
block in Java. A block of code that is run when the application is loaded.
There is no such thing in C++ but it can be faked by using the constructor of a
static object.

foo.cpp:

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


static StaticBlock staticBlock;

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

}

HOWEVER. I've been bitten by this before as it's a subtle edge case of the C++
standard. If the static object is not reachable by any code called by main the
constructor of the static object may or may not be called.

I found that with gcc hello will get output and with visual studio it will
not.

内心荒芜 2024-09-19 06:49:20

我在代码项目上找到了这个答案。它涉及到一个额外的静态变量,但我相信它比 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 <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 编译并运行它并收到友好的“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

I found this answer on The Code Project. It involves having an extra static variable, but I believe it is more reliable than bradgonesurfing's answer. Basically, it is this:

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();

It also means that, like Java's static blocks, you are not required to ever actually have an instance of class Foo, which is useful when the class can take a lot of data, and you simply need to automagically call something before it loads, not instantiate an extra instance of it. You can test that exact code block. I just compiled it (with a little output from static_init(), and had main() print Foo::__st_init, just to make sure), and it worked just fine.

$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)

EDIT:

Sorry that this is so late, but I tested what bradgonesurfing mentioned:

If you test it my accessing the variable in main "just to make sure"
you are ensuring the variable is reachable and thus the variable will
be initialized and thus static_init will be called. Are you sure it
executes if you dont print Foo::__st_init

I used the following inside 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;
}

I compiled with g++ ./main.cpp -o main and ran it and recieved a friendly "Hello, World!" message on my console. Just to be thorough, I also compiled the same version but without the printing and compiled with g++ ./main.cpp -g -o main. I then ran the executable with gdb and had the following result:

(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) 

Here's a more current version output for g++: g++ (Ubuntu 4.8.2-19ubuntu1) 4.8.2

烂人 2024-09-19 06:49:20

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; 
 } 
 ...
}

但这不是线程安全的。有时,在存在多个线程的情况下使其正常工作可能会很困难且棘手。

There is no concept with the name "static block" in C/C++. Java has it however, a "static block" is an initializer code block for a class which runs exactly once, before the first instance of a class is created. The basic concept 'stuff that runs exactly once' can simulated in C/C++ with a static variable, for example:

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; 
 } 
 ...
}

This is not thread-safe however. Getting this working right in the presence of multiple threads can be difficult and tricky sometimes.

寂寞花火° 2024-09-19 06:49:20

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

foo.cpp:

namespace {
    int x;
    int y;
}

在 C 中获得相同的效果

foo.cpp:

static int x;
static int y;

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

In C++ there is the concept of an anonymous namespace.

foo.cpp:

namespace {
    int x;
    int y;
}

to get the same effect in C

foo.cpp:

static int x;
static int y;

In simple terms the compiler does not export symbols from
translation units when they are either declared static or
in an anonymous namespace.

蓝梦月影 2024-09-19 06:49:20

虽然事实上,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,并且可以很好地与旧编译器配合使用。

While indeed, C++ does not have static blocks as part of the language, you can implement static blocks without you (as a user) having to use any classes or namespaces, and can write:

#include "static_block.h" 

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

or whatever else you want. You can't have those within classes, though, just at file scope. See a detailed description of these in my answer to a related question, and the code for static_block.h here.

Note: This does not require C++11 and will work well with old compilers.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文