[解決済み】C++におけるstaticキーワードとその様々な使用法
質問
キーワード
static
C++ではいくつかの意味があり、私は非常に混乱し、実際にどのように動作することになっているのか、自分の考えを曲げることができません。
私が理解したところでは
static
ストレージの持続時間、つまりグローバルの場合はプログラムの寿命まで続きますが、ローカルの場合はデフォルトでゼロ初期化されているということですね。
C++規格では、クラスのデータメンバに対して、このようにキーワード
static
:
3.7.1 静的記憶期間[basic.stc.static]について
3 static キーワードは、静的な保存期間を持つローカル変数を宣言するために使用することができます。
4 クラス定義でクラスデータメンバーに適用されるキーワードstaticは、データメンバーに静的な保存期間を与えます。
とはどういう意味なのでしょうか?
ローカル変数
? それは関数ローカル変数ですか?というのも、関数ローカルを宣言するときに
static
は、この関数に初めて入ったときに一度だけ初期化されるということです。
また、ストレージの持続時間はクラスのメンバーに関してのみ語られており、インスタンスに依存しないことはどうなのか、それはまた
static
ないのか?それとも保管期間?
では
static
とファイルスコープを設定できますか?すべてのグローバル変数は、デフォルトで静的な保存期間を持つとみなされるのでしょうか?以下(3.7.1項)は、そうであることを示しているようです。
1 動的ストレージ期間を持たないすべての変数、スレッドストレージ期間を持たないすべての変数、および ローカルではない は静的記憶期間を持つ。これらの実体の保存期間は,プログラムの継続期間とする(3.6.2,3.6.3)。
どのように
static
は、変数の連結に関係するのでしょうか?
この全体の
static
キーワードは実に紛らわしいのですが、どなたかこのキーワードのさまざまな使い方を明らかにしていただけないでしょうか。
いつ
を初期化するために
static
のクラス・メンバーですか?
解決方法は?
変数
static
変数が存在します。
で定義されている翻訳ユニットです。
とする。
-
名前空間スコープにある場合(つまり関数やクラスの外にある場合)、他の翻訳ユニットからアクセスすることはできません。 これは、内部リンクまたは静的保存期間として知られています。
constexpr
. それ以外の場合は、各翻訳ユニットで別々の変数が使用されることになり、非常に紛らわしいです) - 変数の場合 関数内 他のローカル変数と同じように、関数の外からアクセスすることはできません。(これが彼らの言うローカルです)
-
のため、クラスメンバはスコープを制限されない。
static
しかし、インスタンスと同様にクラスからアドレス指定することができます(たとえばstd::string::npos
). [注意 宣言 クラス内の静的メンバは、通常はまだ 定義 翻訳単位(cppファイル)で、1クラスにつき1つだけです] 。
の場所をコードとして表示します。
static std::string namespaceScope = "Hello";
void foo() {
static std::string functionScope= "World";
}
struct A {
static std::string classScope = "!";
};
翻訳ユニット内の関数が実行される前(場合によっては
main
を実行し始めると、その翻訳ユニット内の静的な保存期間(名前空間スコープ)を持つ変数が "定数初期化"されます(quotは
constexpr
を使用し、非ローカルは適切に"動的初期化"されます。
翻訳ユニットで定義された順番に
(のようなものに対して)。
std::string="HI";
でない場合は
constexpr
). 最後に、関数ローカルの静的要素は、それが宣言されている行に初めて実行が到達したときに初期化されます。 すべて
static
変数はすべて初期化の逆の順序で破壊されます。
このようなことを正しく理解するための最も簡単な方法は、すべての静的変数が
constexpr
を関数スタティックローカルに初期化することで、 どんな場合でもスタティックやグローバルが適切に初期化されるようにし、 その結果として
静的初期化順序の大失敗
.
T& get_global() {
static T global = initial_value();
return global;
}
名前空間スコープ変数がデフォルトで "static storage duration" を持つという仕様は、翻訳ユニットの有効期間" ビットを意味するので、注意が必要です。 ではなく は、ファイルの外からアクセスできないことを意味します。
機能一覧
大幅にわかりやすくなりました。
static
は、クラスのメンバ関数として使われることが多く、独立した関数として使われることはごくまれです。
スタティック・メンバー関数は、通常のメンバー関数と異なり、クラスのインスタンスがなくても呼び出すことができ、インスタンスがないため、クラスの非スタティック・メンバーにアクセスすることができません。 静的変数は、あるクラスに対して、インスタンスのメンバを絶対に参照しない関数を用意したい場合、あるいは
static
メンバ変数
struct A {
A() {++A_count;}
A(const A&) {++A_count;}
A(A&&) {++A_count;}
~A() {--A_count;}
static int get_count() {return A_count;}
private:
static int A_count;
}
int main() {
A var;
int c0 = var.get_count(); //some compilers give a warning, but it's ok.
int c1 = A::get_count(); //normal way
}
A
static
free-functionは、その関数が他の翻訳ユニットで参照されないことを意味し、したがってリンカはその関数を完全に無視することができます。 これにはわずかながら目的があります。
- cppファイルで使用することにより、その関数が他のファイルから決して使用されないことを保証することができます。
- ヘッダーに置くと、すべてのファイルがその関数のコピーを持つことになります。 インラインでもほとんど同じことができるので、有用ではありません。
- 作業軽減によるリンク時間の短縮
-
各翻訳ユニットには、同じ名前の関数を置くことができ、それらはすべて異なることを行うことができます。 例えば
static void log(const char*) {}
をそれぞれの cpp ファイルに配置し、それぞれ異なる方法でログを記録することができます。
関連
-
[解決済み】C++コンパイルタイムエラー:数値定数の前に期待される識別子
-
[解決済み】 != と =! の違いと例(C++の場合)
-
[解決済み】エラー:free(): 次のサイズが無効です(fast)。
-
[解決済み】警告 - 符号付き整数式と符号なし整数式の比較
-
[解決済み】変数やフィールドがvoid宣言されている
-
[解決済み] Swiftのstatic funcとclass funcの違いは何ですか?
-
[解決済み] explicit キーワードの意味は?
-
[解決済み] 静的クラスとシングルトンパターンの違い?
-
[解決済み] Intel CPU の _mm_popcnt_u64 で、32 ビットのループカウンターを 64 ビットに置き換えると、パフォーマンスが著しく低下します。
-
[解決済み】静的初期化コードブロックと非静的初期化コードブロックの違いは何ですか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】コンストラクターでのエラー:識別子を期待されますか?
-
[解決済み】getline()が何らかの入力の後に使用されると動作しない 【重複あり
-
[解決済み】オブジェクト引数のない非静的メンバ関数の呼び出し コンパイラーエラー
-
[解決済み】#include<iostream>は存在するのですが、「識別子 "cout "は未定義です」というエラーが出ます。なぜですか?
-
[解決済み】クラステンプレートの使用にはテンプレート引数リストが必要です
-
[解決済み】C++ - 適切なデフォルトコンストラクタがない [重複]。
-
[解決済み】Enterキーを押して続行する
-
[解決済み】VC++の致命的なエラーLNK1168:書き込みのためにfilename.exeを開くことができません。
-
[解決済み】システムが指定されたファイルを見つけられませんでした。
-
[解決済み】c++で.txtファイルから2次元の配列に読み込む