web-dev-qa-db-ja.com

私のC ++アプリケーションのメソッドのほとんどすべてをインライン化することは良いアイデアか悪いアイデアか?

私はDコーディングに慣れており、Pythonここで、クラス定義には各メソッド定義も含まれています。そのため、これが私の好みのコーディングスタイルです。

.cppファイルに切り替えて、その長い修飾子名を使用する必要はありません。

では、関数を2〜3回以上呼び出すことはめったにないので、コードのほとんどをインライン化するのは良い考えではありませんか?私のコードはライブラリではありません。これは、数学者が使用するデスクトップアプリケーションです。

これは私には理にかなっています。よろしいですか?ありがとう。

2
EnjoysMath

C++を作成するときは、PythonまたはDまたはJavaであるかのように記述しないでください。これらは、 基本的に異なるイディオムを持つ異なる言語です

C++のインライン関数について話すときは、関連しているが異なる2つの概念を区別する必要があります。

  • ヘッダーのinline関数。クラス宣言内の関数定義は暗黙的にinlineです。テンプレートは通常インラインです。

    inline関数(または変数) は、事実上 単一定義ルール(ODR)を無効にします :異なるコンパイルユニットで同じ関数に対して競合する定義が複数ある場合、リンカーは通常エラーを表示します。しかし、inline関数を使用すると、すべての定義が同一であることを約束できます。さらに、インライン関数は、それが定義されたのと同じコンパイル単位からのみ呼び出すことができます。

  • コンパイラー最適化としてのインライン化。 inline関数のセマンティクスはインライン化可能を作成しますが、inlineキーワードは、関数 will がインライン化されることを意味しません。たとえば、インラインで定義されたメンバー関数は、仮想呼び出しなどの間接呼び出しを通じてインライン化することはできません。

    • inline以外の関数のインライン化を可能にするには、フリーの関数/変数(メンバーではない!)のstaticキーワードを使用するか、匿名の名前空間を使用して、 内部リンケージ を指定します。

    • コンパイラ固有の属性を使用できます。たとえば、GCCの __attribute__ ((always_inline)) です。

すべての関数をヘッダーにインラインで定義することはお勧めできません。

  • これにより、コンパイル時間が遅くなりますコンパイル時間。複数のコンパイルユニットを使用することで、インクリメンタルコンパイルを利用できます。これにより、最も簡単なC++プロジェクト以外の作業がより楽しくなります。ただし、不要なコードをヘッダーに挿入した場合は、毎回コード全体を解析、コンパイル、最適化する必要があります。テンプレートは通常、ヘッダーのインライン定義を意味するため、これらのコンパイル時間は、一部のプロジェクトがテンプレートの使用を制限しようとする理由です。

  • 名前空間の汚染およびカプセル化の欠如につながります。かなり多くのコードには、いくつかのプライベートヘルパーが必要になる傾向があります。 Pythonでは、モジュールにアンダースコア関数を追加します。C++では、静的関数または匿名名前空間のコードを追加して、現在のコンパイル単位に制限されます。ただし、すべてがヘッダーにはコンパイルユニットが1つしかありません。これらのヘルパーはすべてすべてのコードに表示され、内部構造は事実上ありません。これにより、名前の競合が発生する可能性もあります。

  • さらに、ヘッダーを含める方法を検討してください。通常のヘッダーと実装の分割では、モジュールのパブリックインターフェイスではなく内部でのみ必要なヘッダーを.cppファイルに含めることができます。これにより、たとえばマクロやグローバル関数などで、そのヘッダーの効果が制限されます。これは、Cライブラリとのインターフェースを取るときに特に重要です。これにより、名前が競合するライブラリ間をブリッジすることもできます。すべてのコードがヘッダーにある場合はそうではありません。含まれているすべての定義は、ヘッダーが含まれているすべてのコンパイル単位でも表示されます。

  • インライン定義は、依存関係を線形化できる場合にのみ機能しますが、循環的または再帰的な依存関係(ツリーノードを表すクラスなど)には使用できません。コードをヘッダーに挿入した場合でも、前方宣言を使用するか、クラス宣言の外でメソッドを定義する必要がある場合があります。そのメソッドがinlineである必要がない場合、ヘッダーでそれを定義しても何も得られません。

ヘッダーと実装ファイルを頻繁に切り替える必要がない場合は、IDEを使用して、宣言と対応する定義の間をより簡単に移動できるようにすることをお勧めします。

はい、C/C++は、すべての歴史的な残骸で非常に迷惑な言語になる可能性があります。そして、はい、Javaコードは読みやすくなる傾向があります。しかし、JavaであるかのようにC++を書いてもメリットは得られません。C++のメリットをあきらめるだけです。同様に、最近のC++は、newでオブジェクトを作成することを避けます。

15
amon

インライン化によってinline関数を使用することを意味する場合、次のことは必要ありません。

  • 現在、主流のコンパイラーはグローバルな最適化を実行し、実際のパフォーマンス上の利点がある場合は自動的に実行します。
  • 標準の言い回しは、コンパイラが行うことにはあまり影響しないことを示しています。

    呼び出しの時点でこのインライン置換を実行するための実装は必要ありません

  • 主な違いは、ヘッダーで関数を定義するかどうかです。 inlineキーワードを使用すると、コンパイラはヘッダーを複数の場所に含めることができます。これは、どこでも同じ関数であることを理解しているためです。 inlineがないと、同じヘッダーが異なるユニットに含まれている場合、One Definition Rule(ODR)に違反する可能性があります。

インライン化によって、メンバー関数定義をヘッダーのクラス定義内に置くことを意味する場合、この方法は推奨されません。各コンパイル単位の同じクラスにまったく同じトークンのシーケンスが使用されている場合、ODRルールに違反しません。しかし、実行するのがより困難なことがいくつかあります(特に、2つのクラス間に相互依存関係がある場合)。クラス定義をその実装から分離すると、カプセル化が促進されるという利点があります。

4
Christophe

私は本当によく文書化されたヘッダーファイルが好きです。それは、知りたいことだけを教えてくれます。クラスとメソッドの名前、メソッドが何をするように仕様化されているのか、です。私はあなたのソースコードを見たくありません。私が欲しいものを読むのが難しくなるだけです。

Swiftはうまく機能します。コードは好きなように記述し、IDEは、ヘッダーファイルを表示したい場合に生成します。それらには、(プライベートメソッドやプロパティがないなど) )。

1
gnasher729