私は最近、マネージ言語がネイティブ言語よりも遅い (または速い) かどうか (具体的には C# と C++) に関する議論を読みました。議論に貢献したある人は、マネージ言語の JIT コンパイラーは、ポインターを使用する言語では不可能な参照に関する最適化を行うことができると述べました。
私が知りたいのは、ポインターではなく参照で可能な最適化の種類は何ですか?
議論はメモリ使用量ではなく、実行速度に関するものであることに注意してください。
私は最近、マネージ言語がネイティブ言語よりも遅い (または速い) かどうか (具体的には C# と C++) に関する議論を読みました。議論に貢献したある人は、マネージ言語の JIT コンパイラーは、ポインターを使用する言語では不可能な参照に関する最適化を行うことができると述べました。
私が知りたいのは、ポインターではなく参照で可能な最適化の種類は何ですか?
議論はメモリ使用量ではなく、実行速度に関するものであることに注意してください。
C ++には、最適化の側面に関連する参照の2つの利点があります。
参照は定数です(存続期間全体にわたって同じ変数を参照します)
このため、コンパイラーは、どの名前が同じ基になる変数を参照しているかを推測しやすくなり、最適化の機会が生まれます。コンパイラが参照をより適切に処理するという保証はありませんが、...
参照は何かを参照していると見なされます(null参照はありません)
「何も参照しない」(NULLポインターに相当する)参照を作成できますが、これはNULLポインターを作成するほど簡単ではありません。このため、NULLの参照のチェックは省略できます。
ただし、これらの利点はいずれも管理対象言語に直接引き継がれないため、ディスカッショントピックのコンテキストではその関連性はわかりません。
ウィキペディアで言及されているJIT コンパイルの利点がいくつかあります。
一般に、JIT コードはインタープリターよりもはるかに優れたパフォーマンスを提供します。さらに、多くの最適化は実行時にしか実行できないため、場合によっては、または多くの場合、静的コンパイルよりも優れたパフォーマンスを提供できます。
- コンパイルは、対象の CPU と、アプリケーションが実行されるオペレーティング システム モデルに合わせて最適化できます。たとえば、JIT は、CPU が SSE2 CPU 命令をサポートしていることを検出すると、SSE2 CPU 命令を選択できます。静的コンパイラでは、おそらくインライン アセンブリを使用して、2 つのバージョンのコードを記述する必要があります。
- システムは、プログラムが置かれている環境で実際にどのように実行されているかに関する統計を収集でき、最適なパフォーマンスを得るために再配置および再コンパイルできます。ただし、一部の静的コンパイラは、プロファイル情報を入力として受け取ることもできます。
- システムは、動的リンクの利点を失うことなく、また静的コンパイラやリンカーに固有のオーバーヘッドなしで、グローバル コードの最適化 (ライブラリ関数のインライン化など) を実行できます。具体的には、グローバルなインライン置換を行う場合、静的コンパイラはランタイム チェックを挿入し、オブジェクトの実際のクラスがインライン メソッドをオーバーライドする場合に仮想呼び出しが発生することを確認する必要があります。
- これは、静的にコンパイルされたガベージ コレクション言語で可能ですが、バイトコード システムではより簡単にメモリを再配置して、キャッシュの使用率を向上させることができます。
ポインターの代わりに参照を使用することに直接関連するものは考えられません。
一般的に言えば、参照によって、異なる場所から同じオブジェクトを参照できるようになります。
「ポインター」は、参照を実装するメカニズムの名前です。C++、Pascal、C... にはポインターがあり、C++ は「参照」と呼ばれる別のメカニズム (わずかに異なる使用例があります) を提供しますが、本質的にこれらはすべて一般的な参照概念の実装です。
したがって、定義上、参照がポインターよりも高速/低速である理由はありません。
本当の違いは、JIT または従来の「事前」コンパイラを使用することです。JIT は、事前コンパイラでは利用できないデータを考慮することができます。「参照」という概念の実装とは何の関係もありません。
他の答えは正しいです。
関数呼び出しを含まないタイトなループ (文字列の比較など) のように、プログラム カウンターが実際に多くの時間を費やすコードでない限り、最適化を行っても大きな違いは生じないことを付け加えておきます。