1. ホーム
  2. c++

C++17のstatic constexpr変数とstatic inline変数の違いは何ですか?

2023-11-02 20:37:26

質問

C++17では、インライン変数が使えるようになりました。

インライン変数の用途の1つは、クラスで定数フィールドを定義することです。

では、この2つの定数定義の違いは何でしょう。

class MyClass {
    static constexpr int myFirstVar = 10;
    static const inline int mySecondVar = 100;
};

もちろん constexprmyFirstVar を暗黙のうちにインライン化します。

ここで、より良い選択は何か、それは constexprinline ?

注意: constnessが必要ない場合は inline を使うと簡単です。とは constexpr では、そのような選択肢はありません。

どのように解決するのですか?

にイニシャライザーを指定する必要はありません。 mySecondVar に初期化子を指定する必要はありません。また、イニシャライザーは constexpr そのものである必要もありません。

このことは、もし私たちが myFirstVar をこのように定義します。

class MyClass {
    static constexpr int myFirstVar;
};

int MyClass::myFirstVar = 1;

あるいはこのように

#include <cstdlib>

class MyClass {
    static constexpr int myFirstVar = rand();
};

どちらにしても不正な形式です。 constexpr の意味論はそれを要求しており、それには正当な理由があります。

inline 指定子のアプローチにより、静的変数の定義をヘッダ自体に含めることができ、イニシャライザが constexpr でなくとも、静的変数の定義をヘッダー自体に含めることができます。

つまり、これは C++17 で完全に有効なヘッダーです。

#include <cstdlib>

class MyClass {
    static const int mySecondVar;
};

inline const int MyClass::mySecondVar = rand();

標準では、ヘッダを含むすべての翻訳ユニットには、実行時までそれが何であるかわからないにもかかわらず、変数に同じ値が表示されることを約束しています。

これはほとんどライブラリライターツールです。あなたのライブラリがヘッダのみであると仮定します。そして昔は、このように定義された静的定数が必要な場合、どのような選択肢があったのでしょうか。

さて、ライブラリと一緒にオブジェクトファイルを出荷してもらうことができます。これは、定数定義だけを含む翻訳ユニットからコンパイルされます。これで、ライブラリはヘッダのみではなくなりました。

または、代わりにインライン関数に依存することもできます。インライン変数の効果は、次のようにして得ることができます。

class MyClass {
    static inline int mySecondVar();
};

inline int MyClass::mySecondVar() {
  static const int value = rand();
  return value;
}

しかし、これは構文の壁の後ろに隠されており、本質的に定数であるものを関数呼び出し演算子で隠しています。