21

ウィキペディアのC++の記事によると

C++ は、プログラマーが誤った選択をする可能性があるとしても、プログラマーに選択を与えるように設計されています。

このように設計されている場合、たとえ私が間違っていたとしても、コンパイラに何かを強制的にインライン化する標準的な方法がないのはなぜですか?

inlineまたは、キーワードが単なるヒントである理由を尋ねることができますか?

ここは仕方がないと思います。

OOP の世界では、オブジェクトのメソッドを呼び出し、メンバーに直接アクセスすることは避ける必要があります。アクセサーを強制的にインライン化できない場合は、高性能でありながら保守可能なアプリケーションを作成することはできません。

(多くのコンパイラがインライン化を強制する独自の方法を実装していることは知っていますが、それは醜いです。マクロを使用してクラスでインラインアクセサーを作成するのも醜いです。)

コンパイラは常にプログラマよりも優れていますか?

4

5 に答える 5

18

コンパイラは再帰関数をどのようにインライン化しますか (特に、コンパイラが末尾呼び出しの最適化をサポートしていない場合や、サポートしている場合でも、関数は末尾呼び出しの最適化に対応していません)。

これは、インラインが実用的かどうかをコンパイラが判断する理由の 1 つにすぎません。他にも、今思いつかないところがあるかもしれません。

于 2011-05-24T09:38:21.863 に答える
5

コンパイラは常にプログラマよりも優れていますか?

いいえ、常にではありません...しかし、プログラマーははるかにエラーを起こしやすく、何年にもわたって最適なチューニングを維持する可能性は低くなります. 肝心なのは、関数が本当に小さい場合 (少なくとも 1 つの一般的/重要なコード パス) にのみインライン化がパフォーマンスに役立つということですが、もちろん多くのことにもよりますが、インライン化は約 1 桁の割合で役立ちます。多くの場合、プログラマーが評価することは実際的ではありません。関数がどれほど些細なことであるかを注意深く監視することは言うまでもありません。しきい値は、コンパイラの実装の選択、コマンド ライン オプション、CPU モデルなどによって変化する可能性があります。関数 - 非組み込み型は、あらゆる種類の異なる動作 (テンプレートでは特に) をトリガーでき、演算子の使用 (new) はオーバーロードされる可能性があるため、呼び出し規則と例外処理手順の冗長性は、一般にプログラマーには明らかではありません。

インライン化された場合に有用なパフォーマンスの向上を期待できるほど小さいものをコンパイラーがインライン化していない場合、コンパイラーは、実際にはそれを悪化させる実装上の問題を認識している可能性があります。コンパイラがどちらの方向にも進む可能性があり、あるしきい値を超えているような灰色のケースでは、いずれにせよパフォーマンスの違いはそれほど大きくない可能性があります。

さらに、一部のプログラマー (私自身も含む) は怠け者であり、ヘッダー ファイルに実装を配置する便利な方法として故意に乱用inline、ODR を回避します。実際にそれらをインライン化する必要があります。ただし、これは強制的なインライン キーワード/表記法を排除するものではありません...現在のキーワードに関する期待を変更するのが難しい理由を説明しているだけです。inline

于 2011-05-24T10:05:33.450 に答える
3

または、インライン キーワードが単なるヒントである理由を尋ねることができますか?

あなたはコンパイラよりもよく知っているかもしれないからです。

ほとんどの場合、インラインとマークされていない (そして正しく宣言/定義されていない) 関数の場合、コンパイラは、その構成と実装に応じて、関数をインライン化できるかどうかを評価します。

たとえば、ほとんどのコンパイラは、コードが長くない場合や複雑すぎる場合、ヘッダーで完全に定義されているメンバー関数を自動的にインライン化します。これは、関数がヘッダーで使用できるため、できる限りインライン化しないのはなぜですか? ただし、これは発生しません。たとえば、Visual Studio のデバッグ モードでは発生しません。デバッグでは、デバッグ情報は関数のバイナリ コードをマップする必要があるため、インライン化は回避されますが、ユーザーが要求したため、インラインとマークされた関数はインライン化されます。それ。これは、デバッグ時のパフォーマンスを向上させながら、デバッグ時の情報 (単純なゲッターなど) を必要としない関数をマークしたい場合に役立ちます。リリース モード (デフォルト) では、コンパイラは可能な限りすべてを積極的にインライン化します。

したがって、一般的な考え方は、コンパイラのインライン化を支援する方法でコーディングすると、可能な限りインライン化されるということです。インライン化が困難または不可能な方法でコードを記述した場合、それは回避されます。何かをインライン化すると、インライン化が困難であるが不可能ではない場合、インライン化する必要があることをコンパイラに伝えるだけです。

インライン化は呼び出し元と呼び出し先の両方のコンテキストに依存するため、「ルール」はありません。多くの場合、インライン関数を明示的にマークすることを単純に無視することをお勧めしますが、次の 2 つの場合があります。

  1. 関数定義をヘッダーに入れる必要がある場合は、インライン化するだけです。多くの場合、テンプレート (メンバーであるかどうかに関係なく) 関数や、単なるショートカットであるその他のユーティリティ関数に当てはまります。
  2. たとえば、特定のコンパイラがコンパイル時に特定の方法で動作するようにする場合は、たとえば、Visual Studio コンパイラのデバッグ構成でも、一部のメンバー関数をインラインにマークしてインライン化するなどです。

コンパイラは常にプログラマよりも優れていますか?

いいえ、それが inline キーワードを使用すると役立つ場合がある理由です。プログラマーは、コンパイラーよりも何が必要なのかについて、より良い一般的な見方を持つことができます。たとえば、プログラマーがバイナリをできるだけ小さくしたい場合、コードによっては、インライン化が有害になる可能性があります。速度性能が要求されるアプリケーションでは、積極的にインライン化することが非常に役立ちます。コンパイラは何が必要かをどのように知るのでしょうか? 構成して、本当にインラインにしたいものをきめ細かく知ることができるようにする必要があります。

于 2011-05-24T09:59:49.700 に答える
0

間違った仮定。

方法はあります。と綴られています#define。多くの初期の C プロジェクトでは、それで十分でした。inline十分に異なっていました-ヒント、より良いセマンティクス-マクロのほかに追加できること。しかし、両方を取得すると、その間に 3 番目のオプションを入れる余地はほとんどなくなりました。

于 2011-05-24T12:27:12.780 に答える
-1

関数のインライン化を強制する必要がある場合 (理由は?)、コードをコピーして貼り付けるか、マクロを使用して実行できます。

于 2011-05-24T09:53:38.980 に答える