constexprについて(C++)
C++の機能として constexpr というものがありますが、const との違いと使いどころがわからなかったので調べました
結論から述べると、どちらも定数を表しますが
const は readonly 変数のように使う
constexpr はコンパイル時に値が決定されるようなときに使う
ということです。
C++ における const というのは変更がなされないという保証がされますという変数のことです
code:sample.c
int get_input(){
int tmp;
std::cin >> tmp;
return tmp;
}
const int sample = get_input();
これは入力の値を sample に代入しています。これ以降 sample は変更されないという保証がされます。
sample はコンパイル時には値が決定しません(入力にどんな値が入るかわからない)
これを constexpr でやってみると
code:sample.c
constexpr int sample = get_input();
コンパイル時に値が決定しませんから勿論エラーになります。
変数に関してマクロ定義で
$ #define hogehoge fugafuga
とかはもうやめて constexpr を使おう
変数についてだけ考えれば大したことない話なのですが、 この constexpr が関数にもつけられてしまいます。
変数と同じで関数がコンパイル時に決定される時に使用するのですが、コンパイル時に決定される関数ってなんだよって思いますよね.yuusuine.iconは思いました
どういうことかというと、コンパイル時に全て計算できますよということを示すだけ
code:lsample.c
constexpr auto func(){
return 100;
}
というだけなんですが、
実は
code:sample.c
constexpr auto func(int& tmp) {
tmp++;
return tmp;
}
少しいじわるな書き方ですが、これはエラーになりません
tmp という変数を受け取ってインクリメントして返すという関数なのでコンパイル時に値が決定しないじゃないかという話ですが、
これは受け渡す変数がコンパイル時に決まるかどうかでエラーになるかどうかが決まります
例えば
code:sample.c
int get_input(){
int tmp;
std::cin >> tmp;
return tmp;
}
constexpr func(int& x) {
x++;
return x;
}
int main(void) {
int tmp = get_input();
func(tmp);
}
これはエラーになります。コンパイル時に決定しない変数を渡していますから.
しかし
code:sample.c
constexpr auto func_1(int x) {
x++;
return x;
}
constexpr auto func_2(int& x) {
x++;
return x;
}
int main(void){
constexpr tmp = 100;
func_1(tmp);
func_2(tmp);
}
これはエラーになりません.constexpr な変数(定数)を渡していますから。
当たり前のように定数を渡して中身を書きかえていますが、エラーになりません。
C++ における定数ってすごく脆いですよね......
これは余談ですが、const ポインタや const_cast を使えば定数なんて定数じゃなくなります。簡単に変数に変更できてしまいます。
C++ がクソな自由度が高くて素晴らしい部分ですよね
constexpr はメンバ関数にも使用できますが、関数と大して変わらないので端折ります
その他注意点としては、ヘッダファイルと実装をわけることはできません。
コンパイル時にインライン展開されるのでヘッダファイルだけあってもエラーが出てしまいます
他にもconstexprの使い方がありそうです.適宜追記していくつもりですが、とりあえず終わりで
#記事
#C++
#constexpr
#const
#yuusuine