我想通过一个例子知道c或c ++中的静态块是什么?我知道什么是静态的,但静态和静态块有什么区别?
答案 0 :(得分:30)
另一种选择是你可能正在寻找静态的类比 在Java中阻止。加载应用程序时运行的代码块。 在C ++中没有这样的东西,但它可以通过使用a的构造函数伪造 静态对象。
foo.cpp:
struct StaticBlock {
StaticBlock(){
cout << "hello" << endl;
}
}
static StaticBlock staticBlock;
void main(int, char * args[]){
}
但是。之前我被它咬过,因为它是C ++的一个微妙优势 标准。如果主要调用的任何代码都无法访问静态对象 静态对象的构造函数可能会也可能不会被调用。
我发现使用gcc hello将获得输出,并且使用visual studio它将会 不
答案 1 :(得分:15)
我在代码项目中找到了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()打印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
答案 2 :(得分: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;
}
...
}
这不是线程安全的。在有多个线程的情况下使这种方法正常工作有时会很困难和棘手。
答案 3 :(得分:1)
虽然C ++没有静态块作为语言的一部分,但可以实现静态块,而无需您(作为用户)必须使用任何类或命名空间,并且可以写:< / p>
#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,并且可以很好地与旧编译器配合使用。
答案 4 :(得分:0)
在C ++中,存在匿名命名空间的概念。
foo.cpp:
namespace {
int x;
int y;
}
在C
中获得相同的效果foo.cpp:
static int x;
static int y;
简单来说,编译器不会从中导出符号 翻译单位,如果它们被声明为静态或 在匿名命名空间中。