web-dev-qa-db-ja.com

C ++の静的グローバル変数

Mallocメソッドを介して整数の配列を作成したいと思います。この配列をグローバルにし、プログラムのどこでも使用できるようにします。次のようなヘッダーファイルにコードを挿入します。

static int *pieces;

次に、そこに必要な数字を入力する関数があります。関数は名前空間にあり、名前空間は独自の.cppファイルに実装されています。ただし、ヘッダーファイルをmain.cにインポートし、次のような配列を作成する名前空間から関数を呼び出します。

pieces = malloc(sizeof(int) * 128);

しかし、(配列を作成する関数を呼び出した後)mainの配列内の数値にアクセスしようとすると、クラッシュして、ピースが初期化されていなかったと表示されます。しかし、私が持っている関数では、それを作成し、その中の数字をうまく操作できます。ピースを静的変数にすることで、どこかの機能が変更(または設定)されるたびに、どこでも変数の使用に影響を与えるという印象を受けました。基本的に私が言おうとしているのは、呼び出した関数に設定したのに、mainでピースが設定されていないように見える理由です。

33
Christian Daley

Staticは多くの意味を持つキーワードであり、この特定のケースでは、not global(言い換え)

つまり、各_.cpp_ファイルには、変数の独自のコピーがあります。したがって、_main.cpp_で初期化すると、__main.cpp_でのみ初期化されます。他のファイルはまだ初期化されていません。

これを修正する最初のことは、キーワードstaticを削除することです。これにより、「複数の定義の問題」が発生します。これを修正するには、変数を_.cpp_ファイルで定義し、ヘッダーファイルでextern宣言するだけです。


編集:メモリを割り当てているだけです。初期化としてカウントします。割り当て後にメモリを0に初期化する必要があります。

より冗長なmalloc構文の代わりにnew int[128]()を使用できます。これは 初期化を実行 にもなりますか?または、簡単な道をたどって(それが何のためにあるのか) _std::vector_ を使用することもできます

61
Karthik T

キーはこれです:

static int *pieces;

あなたはそれをあなたのヘッダーに入れると言った。これは、シンボルをエクスポートする方法ではありません。ヘッダーを含むファイルは、piecesと呼ばれる初期化されていないポインターの独自の静的バージョンを取得します。

代わりに、これをヘッダーに入れます:

extern int *pieces;

extern int init_pieces();

そして、ソースファイルで、あなたはこれをします:

static const size_t num_pieces = 128;

int *pieces = 0;

int init_pieces()
{
    pieces = malloc( num_pieces * sizeof(int) );
    return pieces != NULL;
}

ヘッダーをインクルードすると、ソースファイルは他の場所からpiecesを取得することを認識し、リンカーがどこで機能するかを待機します。また、配列の「init」関数を提案しました。ただし、「リリース」機能は追加しませんでした。

これはすべてCであり、C++ではないことに注意してください。 C++を使用している場合は、newまたはそれ以上を使用する必要があります。vectorを使用します。

また、C++で静的を使用する場合は、次のことに注意してください。 C++静的初期化順序

16
paddy

C++ 17標準では、静的の代わりにinline指定子を使用できます。変数の場合、これはすべてのオブジェクトユニットに変数のコピーがあることを意味しますが、リンカーはそのうちの1つだけを選択します。または、 cppreference に記載されているとおり:

インライン関数またはインライン変数(C++ 17以降)には、次のプロパティがあります。

1)プログラム内にインライン関数またはインライン変数(C++ 17以降)の定義が複数ある場合がありますが、各定義は異なる変換単位に表示されます(非静的インライン関数および変数の場合(C + +17))すべての定義は同一です。たとえば、インライン関数またはインライン変数(C++ 17以降)は、複数のソースファイルに#includeされているヘッダーファイルで定義できます。

2)インライン関数または変数の定義(C++ 17以降)は、アクセス先の翻訳単位に存在する必要があります(アクセスポイントの前である必要はありません)。

3)外部リンケージ(たとえば、静的に宣言されていない)を持つインライン関数または変数(C++ 17以降)には、次の追加のプロパティがあります:

1) It must be declared inline in every translation unit.

2) It has the same address in every translation unit.

source )でサポート:

  • バージョン19.12以降のMSVC(VS 2017 15.5)
  • GCC 7
  • Clang 3.9
  • ICC 18.0

この場合、それはあなたが交換できることを意味します

static int *pieces;

inline int *pieces;
1
topin89

さまざまなアーキテクチャでの高性能なコードの場合、汎用の新しいものではなくmalloc-yの割り当てが必要になる場合があります。これは、mymalloc()のようなものでラップしてから、キャッシュミスを回避するための適切なアライメントを実装したり、IBM(Bluegene)やIntel(MIC)。これらの最適化されたすべての割り当てルーチンには、mallocタイプのフレームワークがあります。

1
Joel Giedt