1. ホーム
  2. c++

クラス内に非整数のstatic constメンバを持つことができないのはなぜですか?

2024-01-02 21:44:42

質問

C++は以下のようにコンパイルできないことに気づきました。

class No_Good {
  static double const d = 1.0;
};

しかし、double 型を int 型、unsigned 型、または任意の整数型に変更するバリエーションは喜んで許可されます。

class Happy_Times {
  static unsigned const u = 1;
};

私の解決策は、それを読み取るように変更することでした。

class Now_Good {
  static double d() { return 1.0; }
};

で、コンパイラは必要なところでインライン化するほど賢いだろうと考えています...しかし、それは私に好奇心を残しました。

なぜC++設計者は、intやunsignedをstatic constにすることを許し、doubleを許さないのでしょうか?

編集: 私は Windows XP 上で Visual Studio 7.1 (.net 2003) を使用しています。

編集2

質問は解決されましたが、完了のために、私が見ていたエラー。

error C2864: 'd' : only const static integral data members can be initialized inside a class or struct

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

問題は、整数の場合、コンパイラが 通常 は定数のためのメモリアドレスを作成する必要がないことです。 それは実行時には存在せず、それを使用するたびに周囲のコードにインライン化されます。 もしそのアドレスが使われるなら(あるいは関数に const 参照で渡されるなら)、それはそうしなければなりません。 アドレスを与えるには、翻訳ユニットで定義する必要があります。 そして、その場合、宣言と定義を分離する必要があります。そうしないと、複数の翻訳ユニットで定義されてしまうからです。

最適化なしのg++を使用し( -O0 ) を使用すると、定数整数変数は自動的にインライン化されますが、定数 double 値はインライン化されません。 より高い最適化レベル(例えば -O1 など) では、定数doubleの値をインライン化します。 したがって、次のコードは -O1 でコンパイルされますが -O0 :

// File a.h
class X
{
 public:
  static const double d = 1.0;
};

void foo(void);

// File a.cc
#include <stdio.h>

#include "a.h"

int main(void)
{
  foo();
  printf("%g\n", X::d);

  return 0;
}

// File b.cc
#include <stdio.h>

#include "a.h"

void foo(void)
{
  printf("foo: %g\n", X::d);
}

コマンドラインです。

g++ a.cc b.cc -O0 -o a   # Linker error: ld: undefined symbols: X::d
g++ a.cc b.cc -O1 -o a   # Succeeds

移植性を最大化するために、定数はヘッダーファイルで宣言し、ソースファイルの中で一度定義する必要があります。 しかし、最適化を有効にすると、コンパイラはもはやそれらの定数を他のソースファイルにインライン化できないため、quot;プログラム全体の最適化"を有効にしない限り、これはパフォーマンスを低下させる可能性があります。