`static const`と` const`のC ++セマンティクス


149

具体的にはC ++では、たとえば次のような意味上の違いは何ですか?

static const int x = 0 ;

そして

const int x = 0 ;

staticリンケージとストレージクラス指定子の両方(つまり、関数の内部と外部)。


7
staticおそらくC ++で最もオーバーロードされたキーワードです。コードの意味は、ネームスペーススコープにあるか、クラススコープにあるか、関数スコープにあるかによって大きく異なります。あなたはそれを明確にしたいかもしれません。
sbi

1
@sbi:もうやったと思った。関数スコープ(ストレージクラス指定子)とファイルスコープ(リンケージ指定子)クラスメンバーと名前空間スコープ変数は、この質問に関しては特に問題ではありませんが、興味深い違いがあると感じた場合は、遠慮なく説明してください。
クリフォード

@クリフォード:最後の言葉を見落としてすみませんでした。ただし、これにより、ユーザー側の誤解が明らかになりました。C++では、ファイルスコープ名前空間スコープです。名前空間の外側で何かを宣言すると、それは単にグローバル名前空間に属します::前に識別子がないプレフィックスを介してアクセスできます)。グローバル名前空間とそれにネストされている名前空間の間に意味のある違いがあることは知りません。確かにstaticオブジェクトに関しては何もありません。
sbi

1
リンケージ可視性とは異なります。それらを交換可能に使用することにより、会話する人々とおそらく自分自身も混乱させることになります。
Ben Voigt

1
@ Ben、@ sbi:ファイルスコープ静的リンクが同じであることを示唆するつもりはありませんでした。静的リンクはファイルスコープを暗示するだけです。この意味で、スコープ(または可視性)は静的および外部リンケージの属性であり、どちらの同義語でもありません。元の質問は明確で整形式であり、sbiのやや下劣な発言に応じて行われたコメントについてのみ議論していると思います。ここでは、私の理解ではなく、不正確な英語のセマンティクスについて説明しているので、やめることができると思います。
クリフォード

回答:


128

ファイルスコープでは、C ++では違いはありません。 const内部リンケージがデフォルトになり、すべてのグローバル変数には静的な有効期間があります。しかし、最初のバリアントはCでも同じ動作をするので、それを使用するのは良い理由かもしれません。

関数内では、2番目のバージョンはパラメーターから計算できます。CまたはC ++では、他の一部の言語が必要とするようなコンパイル時の定数である必要はありません。

クラス内では、基本的に関数の場合と同じです。インスタンスconst値はctor-initializer-listで計算できます。A static constは起動時の初期化中に設定され、残りのプログラムでは変更されません。(注:staticメンバーのコードは、宣言と初期化が分かれているため、少し異なります。)

C ++では、定数ではなく読み取り専用をconst意味することに注意してください。ポインタがあれば、プログラムのほかの部分が見ていなくても値が変わる可能性があります。変数がで定義されている場合、初期化後に誰もそれを変更することはできませんが、初期化は依然として任意に複雑になる可能性があります。constconst


1
ファイルスコープと呼ばれるものはありますか?私は$ 3.3をチェックしていましたが、最も近いのは「名前空間スコープ」だと思います。私の理解は正しいですか?C ++ 03標準では、付録でのみファイルスコープが言及されています
Chubsdad '15 / 09/15

2
私はことを示唆しているファイルのスコープは、リンカーの加工品ではなく、コンパイラなので、言語の標準で多くの注目を取得できない場合があります。厳密には、おそらく「コンパイルユニットスコープ」です。
クリフォード

8
「constは定数ではなく読み取り専用を意味する」というフレーズの+1、つまり「コンパイラー、誰かがこのconstのことを変更しようとしているのを見ると、大声で吠えます。」これが、何かがconst&volatileになる可能性がある理由です。
Dan

5
それは「コンパイラー、私がこのconstのことを変更しようとする(または誰か他の人にそうする許可を与える)のを目にした場合」、より大声で鳴きます。ほとんどのコンテキストでconstは、変数自体ではなく変数のビューに適用され、他の誰かがconst同じ変数の非ビューを持つことができ、コンパイラーが変数を変更するときに非常に静かになります。
Ben Voigt

1
@ベン:明確に言うと、C ++ 0xはその特定の使用法を削除しませんconstが、constexpr代わりに(および他のシナリオでも)新しい方法を使用できます。実際、C ++ 0x標準は、constそのシナリオで使用する機能を非整数型の「リテラル型」にも拡張しています。constexprとにかくC ++ 0x以前のコンパイラとの下位互換性を壊すことになるので、私はそれらの場合に使用することを好むと思います。
Michael Burr

4

C ++ 17標準ドラフトはファイルスコープをconst意味staticします

これは、https//stackoverflow.com/a/3709257/895245で言及された内容の引用です

C ++ 17 n4659標準ドラフト 6.5「プログラムとリンケージ」:

3名前空間スコープ(6.3.6)を持つ名前は、それが

  • (3.1)—静的に明示的に宣言されている変数、関数、または関数テンプレート。または、
  • (3.2)— externが明示的に宣言されておらず、以前に外部リンケージを持つように宣言されていない、非揮発性のconst修飾型の非インライン変数。または
  • (3.3)—匿名組合のデータメンバー。

付録C(参考)互換性、C.1.2条項6:「基本概念」は、これがCから変更された理由を説明します。

6.5 [また10.1.7]

変更:constが明示的に宣言されていて、externが明示的に宣言されていないファイルスコープの名前には内部リンケージがありますが、Cでは外部リンケージがあります。

理論的根拠:C ++での変換中にconstオブジェクトが値として使用される可能性があるため、この機能はプログラマーに各constオブジェクトの明示的な初期化子を提供するように促します。この機能により、ユーザーは、複数の翻訳単位に含まれるソースファイルにconstオブジェクトを配置できます。

元の機能への影響:明確な機能のセマンティクスへの変更。

変換の難しさ:セマンティック変換。

広く使用されている:まれ。

参照:constがCにないのに、C ++の内部リンケージを意味するのはなぜですか?

ヘッダーで代わりに実行する可能性が高いこと

:で詳細に説明した「constの静的」はCやC ++で何を意味するのでしょうか?

  • C ++ 17より前:externヘッダー内、cppファイル内の定義
  • C ++ 17以降:ヘッダーのインライン変数

ありがとう、これはC ++ 98と比較してもC ++ 17でのチャンスではないと思いますが、質問は2010年に尋ねられました。 、そして質問は、異なるコンテキストでのセマンティクスについて具体的に尋ねました。
クリフォード

@Cliffordはい、確かにC ++ 17よりも古く、すべての標準を読むのが面倒です;-)ファイルのスコープ部分を明確にします。
Ciro Santilli郝海东冠状病六四事件法轮功
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.