web-dev-qa-db-ja.com

ゲッターとセッターをオンラインにするのは良い習慣ですか?

public:
     inline int GetValue() const {
          return m_nValue;
     }
     inline void SetValue(int nNewValue) {
          this -> m_nValue = nNewValue;
     }

Learn C++で、彼らはそれがもっと速く動くだろうと言った。したがって、ゲッターとセッターで使用するのは素晴らしいことだと思いました。しかし、おそらくそれにはいくつかの欠点がありますか?

70

プロファイラーがインライン化を行わないとパフォーマンスの問題が発生することを具体的に通知されるまで、何もインライン化しません。

C++コンパイラは非常にスマートで、ほぼ確実にこのような単純な関数を自動的にインライン化します。そして通常、あなたよりも賢く、何をインライン化すべきか、またはすべきでないかを決定する際に、はるかに優れた仕事をします。

インライン化するかしないかを考えてソリューションに集中することは避けます。後でinlineキーワードを追加する(インラインBTWを保証するものではありません)ことは非常に簡単で、プロファイラーを使用して潜在的な場所を簡単に見つけることができます。

56
JaredPar

定義内に記述した場合、それらはinlineデフォルトと見なされます。

これは、それらが複数のコンパイル単位で許可されることを意味します(クラス定義自体は通常複数のコンパイル単位で表示されるため)、not実際にはbeインライン。

29
AraK

これはパブリックAPIの悪い習慣です。これらの関数を変更するには、すべてのクライアントを再コンパイルする必要があります。

一般的にゲッターとセッターを持つことは、抽象化が不十分であることを示しています。常に別のクラスの生データにアクセスする場合は、クラスを再配置する必要があります。代わりに、クラス内のデータの操作方法を検討し、適切なメソッドを提供します。

16
Greg Domjan

マイナス点:

  1. コンパイラーはあなたを無視しても構いません。

  2. これらの機能を変更するには、すべてのクライアントを再コンパイルする必要があります。

  3. 優れたコンパイラーは、適切な場合には非インライン関数をインライン化します。

10
Edward Strange

また、フレームあたり数百万の取得/設定を実行していない限り、これらがインライン化されているかどうかはほとんど無関係です。正直なところ、睡眠を失う価値はありません。

また、宣言+定義の前にWordを「インライン」にしたからといって、コンパイラがコードをインライン化するわけではないことに注意してください。さまざまなヒューリスティックを使用して、それが意味をなすかどうかを判断します。これは、速度とサイズの古典的なトレードオフです。ただし、VC++(GCCに何があるのか​​はわかりません)には、少なくとも強引な '__forceinline'キーワードがあります。これは、コンパイラのファンシーなヒューリスティックを踏みにじります。まったくお勧めしません。別のアーキテクチャに移植すると、間違っている可能性があります。

すべての関数定義を実装ファイルに入れて、ヘッダーの純粋な宣言を残してみてください(もちろん、テンプレートメタプログラミング(STL/BOOST/etc)の場合を除き、この場合、ほとんどすべてがヘッダーにあります;))

人々がインライン化するのを好む古典的な場所の1つ(少なくとも私が出身地であるビデオゲーム)は、数学ヘッダーにあります。クロス/ドット積、ベクトルの長さ、マトリックスのクリアなどがヘッダーに配置されることがよくありますが、これは不要だと思います。 9/10はパフォーマンスに影響を与えません。大きなベクトル配列を何らかのマトリックスで変換するなどのタイトなループを行う必要がある場合は、おそらく手動で数学をインラインで実行するか、プラットフォーム固有のアセンブラ。

ああ、そして別の点として、コードよりも多くのデータを必要とするクラスが本当に必要だと思う場合は、OO抽象化の手荷物をもたらさない、古き良き構造体の使用を検討してください。それが何のためにあるのか:)

申し訳ありませんが、それほど続けるつもりはありませんでしたが、実際のユースケースを検討するのに役立つと思うだけで、コンパイラの設定にこだわる必要はありません(私を信じて、私はそこにいました;))

幸運を。

シェーン

5
Shane

コードは少し長くコンパイルされ、カプセル化が失われます。すべてはプロジェクトの規模とその性質に依存します。ほとんどの場合、複雑なロジックがない場合はインラインにできます。

ところで、クラス定義に直接実装する場合、inlineをスキップできます。

2
Paul

コードをヘッダーに配置することにより、内部クラスの動作を公開しています。クライアントはこれを見て、クラスがどのように動作するかを推測する場合があります。これにより、後でクライアントコードを壊さずにクラスを変更することが難しくなります。

2
Tim Rupe

あなたの場合、インラインキーワードは無意味です

コンパイラは、キーワードに関係なく、可能な場合は関数をインライン化します。

キーワードinlineは、インラインではなくリンクに影響します。少しわかりにくいですが、読んでください。

定義が呼び出しとは異なるコンパイル単位(基本的にプリプロセッサの後のソースファイル)にある場合、インライン化は、プロジェクト全体の最適化とリンク時コード生成が有効になっている場合にのみ可能です。これを有効にすると、リンク時間が大幅に増加します(実際にはリンカ内のすべてが再コンパイルされるため)が、明らかにパフォーマンスが向上する可能性があります。 GCCとVSでデフォルトでオンかオフかはわかりません。

1
Gal

私はあなたがそれを気にする必要はないと言うでしょう。 インライン化に関するFAQセクション を読んでください。

1
mkluwe

少なくともそのような最適化のために、コンパイラを信頼し始める必要はありません!
"しかしいつもではない"

1
Numan

私は、このスレッド上の他の人が持っているように思われるこの慣行に強い嫌悪感を持っていないと言わざるを得ない。インライン化によるパフォーマンスの向上は、最も頻繁に使用される場合を除きすべて無視できることに同意します。 (そして、はい、私はhave実際にそのようなケースに遭遇しました。)この種のインライン化を行う場所では、便宜上、そして一般的にはこのようなワンライナーのためにそれを行います。ほとんどのユースケースでは、クライアント側で変更を加えた場合にクライアント側での再コンパイルを避ける必要性はそれほど強くありません。

はい、inlineを削除できます。これは、実装の配置によって暗示されているためです。

また、アクセッサに対する激怒に少し驚いています。 OO言語を少しも吹き飛ばさずにクラスでくしゃみをすることはほとんどできません。また、インターフェースから実装を抽象化する有効な手法であるため、悪いと主張するのは少し自虐的です。 OO実践。Itisアクセサを無差別に記述しないことをお勧めしますが、それらを根絶するために熱心に夢中にならないこともお勧めします。

純粋主義者よ:-)

0
Owen S.