[解決済み】関数内の静的constexpr変数は意味があるのでしょうか?
質問
関数内に変数がある場合(例えば、大きな配列)、次のように両方宣言することは意味があるのでしょうか?
static
と
constexpr
?
constexpr
は、コンパイル時に配列が作成されることを保証しているので、そのように
static
は無駄なのでしょうか?
void f() {
static constexpr int x [] = {
// a few thousand elements
};
// do something with the array
}
は
static
生成されたコードやセマンティクスに関して、実際にそこで何かを行っているのでしょうか?
どのように解決するのですか?
簡単に言うと
static
は有用であり、常に必要とされるものです。
まず、以下の点に注意してください。
static
と
constexpr
は互いに完全に独立しています。
static
は、実行中のオブジェクトの寿命を定義します。
constexpr
は、コンパイル時にオブジェクトが利用可能であることを指定します。コンパイルと実行は、時間的にも空間的にも不連続であり、不連続です。ですから、プログラムがコンパイルされると
constexpr
はもう関係ない。
を宣言したすべての変数が
constexpr
は暗黙のうちに
const
しかし
const
と
static
との相互作用を除けば)ほぼ直交しています。
static const
整数)
は、その
C++
オブジェクトモデル (§1.9) は、ビットフィールド以外のすべてのオブジェクトが少なくとも1バイトのメモリを占め、アドレスを持つことを要求します。さらに、ある瞬間にプログラム内で観測可能なそのようなオブジェクトはすべて明確なアドレスを持たなければなりません (段落 6)。このことは、ローカルで非静的な定数配列を持つ関数を呼び出すたびに、コンパイラがスタック上に新しい配列を作成することを要求しているわけではありません。
as-if
このようなオブジェクトが他に観測されないことを証明できるのであれば、この原則は適用されません。
配列は多かれ少なかれアドレスであるため、その関数が些細なものでない限り(例えば、翻訳ユニット内で本体が見えない他の関数を呼び出さないなど)、残念ながらそれを証明するのは簡単ではなさそうです。ですから,ほとんどの場合,非静的な
const(expr)
配列は起動のたびにスタック上に再作成する必要があり、コンパイル時に計算できることの意味がなくなります。
一方、ローカルな
static const
オブジェクトはすべてのオブザーバで共有され、さらに、それが定義された関数が一度も呼び出されなかったとしても、初期化される可能性があります。そのため、上記のどれにも当てはまらず、コンパイラはそのインスタンスを1つだけ生成するだけでなく、読み取り専用のストレージに1つだけ生成することも自由にできます。
だから、絶対に
static constexpr
を使用します。
しかし、1つだけ使用したくないケースがあります。
static constexpr
. ただし
constexpr
宣言されたオブジェクトは
ODR-使用
または宣言された
static
の場合、コンパイラはそれを全く含まないという自由があります。これは非常に便利なことで、コンパイル時の一時的な
constexpr
の配列は、コンパイルされたプログラムを不要なバイトで汚染することはありません。このような場合、明らかに
static
というのは
static
は、実行時にそのオブジェクトを強制的に存在させる可能性があります。
関連
-
[解決済み] [Solved] Error C1083: Cannot open include file: 'stdafx.h'
-
[解決済み】「corrupted size vs. prev_size」glibc エラーを理解する。
-
[解決済み】Visual Studio 2013および2015でC++コンパイラーエラーC2280「削除された関数を参照しようとした」が発生する
-
[解決済み】変数やフィールドがvoid宣言されている
-
[解決済み】エラー。引数リストに一致するコンストラクタのインスタンスがない
-
[解決済み] C言語における「static」の意味とは?
-
[解決済み] Pythonの関数内の静的変数に相当するものは何ですか?
-
[解決済み] C++の関数内のスタティック変数のライフタイムは?
-
[解決済み】C言語の「static」関数とは?
-
[解決済み】静的な constexpr char[] への未定義の参照]
最新
-
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 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】コンストラクターでのエラー:識別子を期待されますか?
-
[解決済み】Visual Studio 2015で「非標準の構文。'&'を使用してメンバーへのポインターを作成します」エラー
-
[解決済み】テンプレートの引数1が無効です(Code::Blocks Win Vista) - テンプレートは使いません。
-
[解決済み】C++プログラムでのコンソールの一時停止
-
[解決済み】c++でstd::vectorを返すための効率的な方法
-
[解決済み】「std::operator」で「operator<<」にマッチするものがない。
-
[解決済み】ファイルから整数を読み込んで配列に格納する C++ 【クローズド
-
[解決済み] 解決済み] `pthread_create' への未定義の参照 [重複] [重複
-
[解決済み】C++ - ステートメントがオーバーロードされた関数のアドレスを解決できない。
-
[解決済み】Enterキーを押して続行する