#defineとconst, constexpr
定数設定によく使うdefineとconst, constexprですが、これらには大きな違いがあります。
#define
マクロです。マクロですので変数, 定数でなく、ただ値を置き換えます。つまり、実体が存在しません。定数として使う場合、メモリ使用量はほとんどありません。
また、ソースコードの置き換えを行うので、値だけでなく、
#include <iostream>
#define rep(i, n) for (int i = 0; i < (int)(n); i++) // https://atcoder.jp/contests/apg4b/tasks/APG4b_an
rep(i, 5) {
std::cout << i << std::endl;
}
というようなことも可能です。
const
定義後不変の値です。関数の引数やクラスのコンストラクタでとることができます。
void hoge(const int) {
// 処理
}
class huga {
public:
huga(int num) :
num(num) { // 初期化子リストで定義
}
private:
const int num; // 宣言
};
constexpr
コンパイル時確定の定数です。アドレスを取得する場合メモリ確保が行われますが、そうでない場合は最適化によって実体を持ちません。
また#defineと異なり変数であるため、スコープ管理が可能です。(グローバルでなくせる)
#include <iostream>
constexpr int num_a = 100;
constexpr int num_b = 200;
std::cout << num_a << std::endl; // 最適化で実体なし
const int* ptr_b = &num_b; // 実体あり
std::cout << *ptr_b << std::endl; // (これぐらいなら最適化されるかも)
まとめ
コンパイル時確定の定数であれば#defineよりもconstexprを使うことを推奨します。