1

大きな関数をインラインで宣言し、コンパイラがそれをスタンドアロン関数としてコンパイルすることを選択した場合、プログラム内のそのインライン化されていないインライン関数のコピーが 1 つだけであることが保証されているか、それともコンパイラが複数の非インライン関数を作成することになるか-異なる翻訳単位でのこの関数のインラインコピー?

または、歯ぎしりを引き起こすことがほぼ確実な方法で言い換えると、前処理時間が問題にならない場合、ヘッダーファイルでインラインで大きなメソッドを定義することは、コードを再利用することなくそのコードを再利用できる効果的な方法です。別の翻訳単位でコンパイル/リンクするには?

4

3 に答える 3

3

大きな関数をインラインで宣言し、コンパイラがそれをスタンドアロン関数としてコンパイルすることを選択した場合、プログラム内にインライン化されていないインライン関数のコピーが 1 つだけ存在することが保証されますか?

いいえ、そのような保証はありません。保証されているのは、関数で宣言された静的変数のコピーが 1 つだけ存在すること、および関数のアドレスを取得すると、常に同じ値が得られることです。

または、コンパイラは、この関数の複数のインライン化されていないコピーを異なる翻訳単位で作成することになるのでしょうか?

かもしれない。それらは同一ではないかもしれません: 1 つの翻訳単位で引数が常に null であることがわかる場合は、if (arg != nullptr)...` のコードを省略できます。

于 2016-10-14T10:24:22.890 に答える
3

保証を求めているため、ここでは非常に具体的にする必要があります。C++ 標準は、実装ではなくプログラムの動作を保証しており、悪意のあるコンパイラから保護するようには書かれていません。多くの実装の詳細は、動作によって効果的に制約されます。しかし、完全ではありません。

コンパイラは、インラインかどうかに関係なく、任意の関数の 2^17 の異なるコピーを実行可能ファイルに自由に埋め込むことができます。これは無意味ですが、規格では禁止されていません! 静的変数の値とアドレスは、監視可能であるため共有する必要があり、C++ コードがそれらを取得できる場合、各関数へのすべての関数ポインターは等しいと比較する必要があります (アドレスの別個のバイナリ表現を持つことができます。 !)を実行することの意味を変更し==ます)。

これは起こりますか?いいえ、しかしあなたは保証を求めました。C++ 標準では、実装者に大きな自由度が残されています。実装の品質とは、最新のコンパイラが愚かなことを頻繁に行わないことを意味します。

.o実際には、それを使用する各ファイルに 1 つのインライン関数が作成されます。特別 (「弱い」) としてマークされます。静的にリンクする場合、これらのコピーの 1 つを除くすべてが破棄されます。どちらが保持されるかは、リンクの順序に依存し、ビルドごとに異なる場合があります (特に部分ビルド)。静的ローカルの 1 つのコピーのみが同様の方法で保持されます。関数へのすべてのポインターまたは内部の静的ローカルは、実行時に等しくなければなりません。

動的リンクは、DLL に組み込まれるときに一部のコンパイラで破棄されます。が読み込まれると、他のコンパイラ.soは、シンボルが既に読み込まれているかどうかを確認し、読み込まれている場合はコピーを に読み込みません.so。動的リンクは、関数の複数のコピーが引き続き存在し、アクセスされる可能性が最も高いケースです。このケースが発生していない場合は問題がなく、発生している場合はテストしてください。C++ 標準では、動的リンクについて説明していません。

于 2016-10-14T11:01:47.280 に答える
0

以下の質問を確認することをお勧めします:
「インライン」キーワードと「インライン化」の概念

最適化の目的で、inline関数が次の場合:

  • 十分に大きい場合、コンパイラは「インライン化」を実行しない場合があります
  • 十分に短い場合、コンパイラは「インライン化」を行う可能性があります

ただし、どちらの場合も、キーワードを使用しているため、 1 つの定義ルール (ODR)が保証されます。inline

于 2016-10-14T10:12:18.443 に答える