2012-12-13 9 views
26

私はC++プロジェクトにパーティクルシステムエンジンを持っています。パーティクル自体は、機能のない変数の構造体です。現在、各パーティクル(パーティクル)は、変数に直接アクセスすることによって、その親クラス(パーティクルシステム)から更新されます。例えば。ゲッターとセッター。パフォーマンスのオーバーヘッドはありますか?

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

私の質問は次のとおりです:ただまっすぐにデータアップとは対照的にゲッターとセッターを呼び出してから、任意のパフォーマンスのオーバーヘッドがあります

particle.x += particle.vx; 

は、私はこのようなゲッターとセッターを使用して議論し、しかしですアクセス?結局のところ

取得および設定すると、少し複雑なタスクであることが判明した場合、私が通じ更新する多くの粒子を多く持っている...

+1

setters/getterは、主にコードの可読性/保守性を目的としています。関数を呼び出すと、まっすぐなデータアクセスよりもパフォーマンスのオーバーヘッドが発生します。 –

+2

ゲッターとセッターは、データをカプセル化してアクセスするためのものです。パフォーマンス上のオーバーヘッドはなく、単純なgetterとsetterはコンパイラによってインライン展開されます。 –

+3

@habeebperwad:読みやすさをどのように向上させるのか想像もできませんが、実際には実装を変更することが容易になります。 –

答えて

39

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

ただし、ゲッターやセッターを使用するのは、その変数を取得または設定して、追加の副作用が発生する可能性があるからです。オブジェクトの位置を変更すると、物理シミュレーションなどの近くのオブジェクトの位置も変更されます。

最後に、最適化されたコードのコンテキスト内でゲッターとセッターの操作のオーバーヘッドは非常に小さく、コードが熱くない限り心配する必要はありません。また、暑い場合は、ゲッターやセッターをヘッダーファイルに移動してインライン展開するのも簡単です。

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

+3

+1はインライン展開になります(ただし残りはあまりにも上です)。インラインで忘れてください。 – MPelletier

+0

どのように最適化しますか? getterのconstを追加しますか? – sgtHale

+4

しかし、関数をインライン展開することは、a)提案のみであり、b)ソースファイルに利用可能なすべての情報がある場合にのみ機能し、ヘッダーに含める必要があることを覚えておいてください。 – OmnipotentEntity

4

ゲッターとセッターは、あなたのコードは、将来的にはより簡単に進化することができます。ほとんどのC++コンパイラは、これらの単純なメソッドinlineに十分スマートであり、関数呼び出しのオーバーヘッドを排除します。

2

この質問にはさまざまな回答がありますが、ここに私の考えを入れています。

性能面では、シンプルなPODタイプではコストがほとんど無視できます。 しかし、まだコストがあり、あなたが返すタイプによって異なります。パーティクルの場合、データはあまりありません。これが画像クラス(OpenCV cv :: Matのような)または3dデータ(VTKのPolyDataのような)の場合、メモリー割当ての問題を避けるためにsetter/getterが実際のデータよりポインタ/イテレータを処理する方が良いです。

テンプレートを作成したいときは、明示的な型変換を避けるためにsetter/getterを使うと非常に便利です。 setter/getterはprivate/protectedメンバにアクセスする方法です。変数の共通名としてxを使わないようにすることもできます。さらにsetter/getterはLvalue参照を返すことができます。particle.getX() = 10.0 ;

+0

particle.getX()= 10.0; - しかし、どこでそれが必要なのですか? – SChepurin

+2

@SChepurinカプセル化を中断するだけでなく、恐ろしく*破ってもらいたいときは? –

+0

@MichaelKjörling、私はこれがより自然で、なぜカプセル化を破ると言うのでしょうか? –

14

これまでの回答とは違う意見があります。

getterとsetterは、クラスが有用な方法で設計されていないという兆候です。内部実装から外部動作抽象を作成しない場合は、最初に抽象インターフェイスを使用する必要はありません。単純な古い構造体を使用することもできます。

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

内部コンポーネントx,y ... vzに外部からアクセスできない場合、モジュール外部のコードを制動することなく安全に内部実装を変更できます。それはかなりゲッター/セッター全体のポイントです。しかし、これらを使用すると、できるだけ多くの最適化ができます。実装の実際の変更は、必然的にゲッターをずっと遅くすることになります。
一方、SIMD操作、外部ライブラリ呼び出し(おそらくCUDAのような高速化されたハードウェア上)などを使用して、ベクトルベースのインターフェイスから最適化することができます。 to_posarrayのような「バッチゲッター」は、依然として合理的に効率的に実装することができます。


*私はstd::vectorを好きではない、ここmathematical senseにベクトルを意味します。

関連する問題