質問
こちらからこの見積もりをご覧ください、ページの下部に向かって。 ( const
sに関する引用されたコメントは、 invariant
sにも適用されると思います)
列挙は、スペースを消費しないという点でconstと異なります。 最終出力オブジェクト/ライブラリ/実行可能ファイルでは、constsはそうです。
だからどうやら value1
は実行可能ファイルを膨張させますが、 value2
はリテラルとして扱われ、オブジェクトファイルには現れません。
const int value1 = 0xBAD;
enum int value2 = 42;
C ++に戻ると、私は常にこれがレガシーな理由と、定数を最適化することができなかった古いコンパイラのためだと思っていました。しかし、これがまだDに当てはまる場合は、この背後にもっと深い理由がなければなりません。誰でもその理由を知っていますか?
解決
C ++と同じように、Dの列挙型は" conserved integer literal"のようです。 (編集:驚くべきことに、D2はフロートと文字列さえもサポートしています。 a>)。その列挙子には場所がありません。それらは、アイデンティティのない価値として重要ではありません。
enum
の配置はD2の新機能です。最初に新しい変数を定義します。これは左辺値ではありません(そのため、そのアドレスを取得することもできません)。
enum int a = 10; // new in D2
似ている
enum : int { a = 10 }
もし私が貧しいDの知識を信頼できるならしたがって、ここの a
は左辺値ではありません(場所はなく、そのアドレスを取得することはできません)。ただし、constはアドレスを持っています。グローバル(これが正しいD用語かどうかわからない)const変数がある場合、コンパイラーは通常、最適化できません。どのモジュールがその変数にアクセスできるか、そのアドレスを取ることができないためです。そのため、ストレージを割り当てる必要があります。
ローカルconstがある場合、コンパイラはC ++の場合と同じように最適化できると思います。なぜなら、コンパイラはスコープを見て、アドレスに関心があるかどうか、または誰もが値を取得するかどうかを知るからです。
他のヒント
実際の質問。 Dでenum / constがC ++と同じである理由;未回答のようです。残念ながら、この選択をする理由は何もありません。これは、C ++の意図しない副作用であり、事実上のパターンになったと考えています。 Dでは同じパターンが必要でしたが、ウォルター・ブライトは、その場所から来た人が何をすべきかを認識するようにC ++のように行うべきであると決定しました...実際、このむしろIMHO愚かな決定の前に、キーワードマニフェストが使用されましたこのユースケースの列挙の代わりに。
優れたコンパイラ/リンカーは定数をまだ削除すべきだと思います。列挙型を使用するだけで、仕様で実際に保証されます。違いは主にセマンティクスの問題です。 (2.0はまだ完全ではないことにも注意してください)
enum
が構文的に拡張されて単一のマニフェスト定数をサポートすることの本当の目的は、Dテンプレートの第一人者であるDon Clugstonがテンプレートでおかしなことをしていたことです。コンパイラーはconst変数の内部データ構造を作成し続けたため、彼は長いビルド時間、ばかげたコンパイラーのメモリ使用量などに出くわし続けました。列挙型と比較したconst / immutable変数の重要な点の1つは、const / immutable変数は左辺値であり、アドレスを取得できることです。これは、コンパイラに余分なオーバーヘッドがあることを意味します。通常、これは問題になりませんが、実際に複雑なコンパイル時メタプログラムを実行している場合、const変数が最適化されていなくても、コンパイル時のオーバーヘッドはかなり大きくなります。
列挙値は「インライン」で使用されるようです。式では、constが実際にストレージを取得し、それを参照する式がメモリストレージから値をロードします。
この音は、C#のconstとreadonlyの違いに似ています。前者はコンパイル時定数で、後者は実行時定数です。これは、アセンブリのバージョン管理に確実に影響します(読み取り専用を参照するアセンブリはコンパイル時にコピーを受け取り、参照されるアセンブリが異なる値で再構築された場合、値の変更を取得しません)。