cまたはc ++の静的ブロックとは何か、例を挙げて知りたいですか? 何が静的かは知っていますが、静的ブロックと静的ブロックの違いは何ですか?
5 に答える
もう1つの方法は、Javaの静的ブロックの例えを探している可能性があることです。アプリケーションのロード時に実行されるコードのブロック。C ++にはそのようなものはありませんが、静的オブジェクトのコンストラクターを使用して偽造することができます。
foo.cpp:
struct StaticBlock {
StaticBlock(){
cout << "hello" << endl;
}
}
static StaticBlock staticBlock;
void main(int, char * args[]){
}
でも。これはC++標準の微妙なエッジケースであるため、以前はこれに悩まされていました。mainによって呼び出されたコードが静的オブジェクトに到達できない場合、静的オブジェクトのコンストラクターが呼び出される場合と呼び出されない場合があります。
gcc helloでは出力が得られますが、VisualStudioでは得られないことがわかりました。
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() print 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が言及したことをテストしました:
「確認のために」メインの変数にアクセスしてテストすると、変数が到達可能であることを確認できるため、変数が初期化され、 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
C/C++ には「静的ブロック」という名前の概念はありません。Javaにはそれがありますが、「静的ブロック」は、クラスの最初のインスタンスが作成される前に1回だけ実行されるクラスの初期化コードブロックです。「一度だけ実行されるもの」という基本概念は、静的変数を使用して 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
hereのコードを参照してください。
注:これは C++11 を必要とせず、古いコンパイラでもうまく機能します。
C++ には、匿名名前空間の概念があります。
foo.cpp:
namespace {
int x;
int y;
}
Cで同じ効果を得るには
foo.cpp:
static int x;
static int y;
簡単に言えば、コンパイラは、シンボルが静的または匿名の名前空間で宣言されている場合、翻訳単位からシンボルをエクスポートしません。