[解決済み] constexpr` と `const` の相違点
質問
とはどう違うのですか?
constexpr
と
const
?
- どちらか一方だけを使用できるのはどんな場合ですか?
- 両方使えるのはどんなときで、どのように選べばいいのでしょうか?
どのように解決するのですか?
基本的な意味と構文
どちらのキーワードも、関数と同様にオブジェクトの宣言に使用することができます。基本的な違いは オブジェクト はこうです。
-
const
としてオブジェクトを宣言しています。 定数 . これは、一度初期化されたオブジェクトの値は変化しないという保証を意味し、コンパイラはこの事実を利用して最適化を行うことができる。また、プログラマーが、初期化後に変更されることを意図していないオブジェクトを変更するようなコードを書くのを防ぐのにも役立つ。 -
constexpr
で使用するのに適したオブジェクトであると宣言しています。 定数式 . しかし、以下のことに注意してください。constexpr
が唯一の方法というわけではありません。
に適用した場合 機能 基本的な違いは次のとおりです。
-
const
は非静的メンバ関数にのみ使用でき、一般的な関数には使用できません。これは、メンバ関数が非静的データメンバを一切変更しないことを保証するものです (ただし、変更可能なデータメンバは例外で、どのみち変更される可能性があります)。 -
constexpr
は、メンバ関数と非メンバ関数、およびコンストラクタで使用することができます。での使用に適した関数を宣言します。 定数式 . コンパイラは、その関数が特定の基準 (7.1.5/3,4) を満たしている場合にのみ、これを受け付けます。 (†) :-
関数本体は非仮想的で極めて単純でなければならない。型定義と静的アサートは別として、関数本体には単一の
return
ステートメントを使用することができます。コンストラクタの場合、初期化リスト、型定義、スタティックアサートのみが許される。(= default
と= delete
も許されますが)。 -
C++14では、よりルールが緩和され、constexpr関数内でそれ以降許可されているもの。
asm
宣言にgoto
ステートメント以外のラベルを持つステートメントはcase
とdefault
try-block、非リテラル型の変数の定義、static または thread storage duration の変数の定義、初期化が行われない変数の定義。 - 引数と戻り値の型は、必ず リテラル型 (すなわち、一般的に言えば、非常に単純な型、典型的にはスカラーまたは集合体)
-
関数本体は非仮想的で極めて単純でなければならない。型定義と静的アサートは別として、関数本体には単一の
定数表現
上述したように
constexpr
は、オブジェクトと関数の両方を定数式で使用するのに適したものとして宣言しています。定数式は、単に定数であるだけではありません。
-
テンプレートパラメータや配列サイズ指定子など、コンパイル時の評価が必要な場所で使用することができます。
template<int N> class fixed_size_list { /*...*/ }; fixed_size_list<X> mylist; // X must be an integer constant expression int numbers[X]; // X must be an integer constant expression
-
でも、注意してください。
-
として何かを宣言する
constexpr
は、必ずしもコンパイル時に評価されることを保証するものではありません。それは を使用することができます。 がありますが、実行時に評価される他の場所でも使用することができます。 -
オブジェクト かもしれない 定数式で使用するのに適している がなければ 宣言されている
constexpr
. 例int main() { const int N = 3; int numbers[N] = {1, 2, 3}; // N is constant expression }
これが可能なのは
N
は定数であり、宣言時にリテラルで初期化されるため、たとえ宣言されていなくても定数式の基準を満たします。constexpr
.
では、実際にどのような場合に
constexpr
?
-
An
オブジェクト
のように
N
は定数表現として使用することができます。 なし と宣言されています。constexpr
. であるすべてのオブジェクトに当てはまります。 -
const
- 積分型または列挙型の と
-
宣言時にそれ自体が定数式である式で初期化されます。
<サブ [これは§5.19/2によるものです:定数式は、[...]整数型または列挙型の[...]値でない限り、"値から値への変更を伴う部分式を含んではなりません; これがすべてのリテラル型について正しいという私の以前の主張を修正してくれたリチャード・スミスに感謝します]。
-
の場合 機能 を定数式で使用するのに適している場合、それは 必要なのは 明示的に宣言される
constexpr
単に定数式関数の基準を満たすだけでは十分ではありません。例template<int N> class list { }; constexpr int sqr1(int arg) { return arg * arg; } int sqr2(int arg) { return arg * arg; } int main() { const int X = 2; list<sqr1(X)> mylist1; // OK: sqr1 is constexpr list<sqr2(X)> mylist2; // wrong: sqr2 is not constexpr }
どのような場合に両方を使うことができますか/使うべきですか。
const
と
constexpr
一緒に?
A. オブジェクト宣言の中で
両方のキーワードが宣言される同じオブジェクトを参照している場合、これは決して必要ではありません。
constexpr
を意味します。
const
.
constexpr const int N = 5;
と同じです。
constexpr int N = 5;
ただし、キーワードがそれぞれ宣言の異なる部分を指している場合もあるので、注意が必要です。
static constexpr int N = 3;
int main()
{
constexpr const int *NP = &N;
}
ここです。
NP
はアドレス定数式、すなわちそれ自体が定数式であるポインタとして宣言されています。(これは、アドレスが静的/グローバル定数式にアドレス演算子を適用して生成される場合に可能です)。ここでは、両方の
constexpr
と
const
が必要です。
constexpr
は常に宣言されている式を参照します(ここでは
NP
であるのに対し
const
とは
int
(ポインタ-to-constを宣言している)。を削除すると
const
は式を不正にします(なぜなら (a) 非恒等式オブジェクトへのポインタは定数式になり得ないし、(b)
&N
は実際には定数へのポインタである)。
B. メンバ関数宣言の中で
C++11の場合。
constexpr
を意味します。
const
C++14とC++17ではそうではありません。C++11で次のように宣言されたメンバ関数は
constexpr void f();
として宣言する必要があります。
constexpr void f() const;
として使用できるようにするため、C++14のもとで
const
関数を使用します。
関連
-
[解決済み】coutはstdのメンバではない
-
[解決済み】C++エラーです。"配列は中括弧で囲まれたイニシャライザーで初期化する必要がある"
-
[解決済み】リンカーエラーです。"リンカ入力ファイルはリンクが行われていないため未使用"、そのファイル内の関数への未定義参照
-
[解決済み】演算子のオーバーロード C++; <<操作のパラメータが多すぎる
-
[解決済み] ルール・オブ・スリーとは?
-
[解決済み] C++11では、標準化されたメモリモデルが導入されました。その意味するところは?そして、C++プログラミングにどのような影響を与えるのでしょうか?
-
[解決済み] スマートポインターとは何ですか?
-
[解決済み] const int*、const int * const、int const *の違いは何ですか?
-
[解決済み] C#のconstとreadonlyの違いは何ですか?
-
[解決済み] g++とgccの違いは何ですか?
最新
-
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で「非標準の構文。'&'を使用してメンバーへのポインターを作成します」エラー
-
[解決済み】C-stringを使用すると警告が表示される。"ローカル変数に関連するスタックメモリのアドレスが返される"
-
[解決済み】C++のGetlineの問題(オーバーロードされた関数 "getline "のインスタンスがない
-
[解決済み】デバッグアサーションに失敗しました。C++のベクトル添え字が範囲外
-
[解決済み】浮動小数点例外エラーが発生する: 8
-
[解決済み] 式はクラス型を持つ必要があります。
-
[解決済み】#include<iostream>は存在するのですが、「識別子 "cout "は未定義です」というエラーが出ます。なぜですか?
-
[解決済み】浮動小数点数の乱数生成
-
[解決済み】演算子のオーバーロード C++; <<操作のパラメータが多すぎる
-
[解決済み】エラー。引数リストに一致するコンストラクタのインスタンスがない