web-dev-qa-db-ja.com

ゲッターとセッター。パフォーマンスのオーバーヘッドはありますか?

C++プロジェクトにParticleSystem Engineがあり、パーティクル自体は関数のない変数の構造体にすぎません。現在、各パーティクル(Particle)は、変数に直接アクセスすることにより、親クラス(ParticleSystem)から更新されています。例えば。

_particle.x += particle.vx;
_

しかし、私は次のようなゲッターとセッターを使用して議論しています:

particle.setX( particle.getX()+particle.getVX() );

私の質問は次のとおりです:データアクセスをまっすぐにするのではなく、ゲッターとセッターを呼び出すことによるパフォーマンスのオーバーヘッドはありますか?

結局のところ、更新するパーティクルはたくさんあります...

36
sgtHale

セッターとゲッターにはパフォーマンスのオーバーヘッドがあります最適化されていない場合ほとんどの場合、リンク時間の最適化を行うコンパイラーで最適化されます。また、そうでないコンパイラーでは、関数本体の知識がある場合(つまり、プロトタイプだけでなく)、最適化されます。

ただし、ゲッターを使用し、その変数を取得または設定して追加の副作用を持たせたい場合があるため、セッターがあります。オブジェクトの位置を変更するのと同様に、物理シミュレーションなどで近くのオブジェクトの位置も変更します。

最後に、最適化されたコードのコンテキスト内でのゲッターおよびセッター操作のオーバーヘッドは非常に小さく、コードがホットでない限り心配する価値はありません。また、暑い場合は、ゲッターまたはセッターをヘッダーファイルに移動してインライン化するだけでSO簡単です。

つまり、ゲッターとセッターは、オブジェクトで発生する可能性のあることと発生しないことを非常に具体的に指定でき、変更をマーシャリングできるため、マイナーまたは存在しないオーバーヘッドの価値が十分にあります。

52

私はこれに対して以前の回答とは異なる意見を持っています。

ゲッターとセッターは、クラスが有用な方法で設計されていないことを示しています。内部実装から外部動作を抽象化しない場合、そもそも抽象インターフェースを使用しても意味がありません。昔ながらの構造体。

本当に必要な操作について考えてください。それはほぼ確実ですnot位置と運動量のx-y-およびz座標への直接アクセス、あなたはむしろこれらをベクトル量として扱いたいです(少なくともほとんどの計算では、これはに関連するすべてです最適化)。したがって、基本的な操作がベクトルの加算、スケーリング、内積であるベクトルベースのインターフェイス*を実装する必要があります。コンポーネントごとのアクセスではありません。たぶんそれをする必要があるかもしれませんが、これは単一のstd::array<double,3> to_posarray()メンバーまたはそのようなもので行うことができます。

内部コンポーネントxy ... vzに外部からアクセスできない場合は、モジュールの外部のコードにブレーキをかけることなく、内部実装を安全に変更できます。これは、ゲッター/セッターのほぼすべてのポイントです。ただし、これらを使用する場合、実行できる最適化はそれほど多くありません。実装を実際に変更すると、必然的にゲッターの速度が大幅に低下します。
一方、SIMD操作、外部ライブラリ呼び出し(CUDAなどの高速ハードウェア上で)などを使用して、ベクトルベースのインターフェイスから地獄を最適化することができます。 to_posarrayのような「バッチゲッター」は、まだかなり効率的に実装できますが、単一変数セッターは実装できません。


*ここでは、std::vectorとは異なり、 数学的な意味 のベクトルを意味します。

14
leftaroundabout

ゲッターとセッターを使用すると、取得と設定が少し複雑なタスクであることが判明した場合に、コードを将来より簡単に進化させることができます。ほとんどのC++コンパイラは、 inline これらの単純なメソッドを実行し、関数呼び出しのオーバーヘッドを排除するのに十分なほどスマートです。

4
Reuben Morais

この質問にはさまざまな答えがあるかもしれませんが、私はここに私の考えを置きました。

パフォーマンスに関しては、単純なPODタイプのコストはほとんど無視できます。しかし、それでもコストがかかり、それはあなたが返すタイプに依存します。粒子については、多くのデータがありませんでした。これが画像クラス(OpenCV cv :: Matなど)または3Dデータ(VTKのPolyDataなど)の場合、メモリ割り当ての問題を回避するために、setter/getterが実際のデータよりもポインター/イテレーターを処理することをお勧めします。

物事をテンプレート化したい場合、setter/getterは、不明確な型変換を回避するのに非常に役立ちます。セッター/ゲッターは、プライベート/保護されたメンバーにアクセスする方法であり、変数の共通名としてxを使用することを回避することもできます。さらに、setter/getterは、particle.getX() = 10.0 ;を実行できるLvalue参照を返すことができます。

2
tomriddle_1234