41

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

particle.x += particle.vx;

ただし、次のようなゲッターとセッターの使用について議論しています。

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

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

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

4

5 に答える 5

61

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

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

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

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

于 2012-12-13T05:31:04.167 に答える
16

I have a different opinion to this than the previous answers.

Getters and setters are signs that your class isn't designed in a useful way: if you don't make the outer behaviour abstract from the internal implementation, there's no point in using an abstract interface in the first place, you might as well use a plain old struct.

Think about what operations you really need. That's almost certainly not direct access to the x- y- and z-coordinates of position and momentum, you rather want to treat these as vector quantities (at least in most calculations, which is all that's relevant for optimisation). So you want to implement a vector-based interface*, where the basic operations are vector addition, scaling and inner product. Not component-wise access; you probably do need to do that sometimes as well, but this can be done with a single std::array<double,3> to_posarray() member or something like that.

When the internal components x, y ... vz aren't accessible from the outside, you can then safely change the internal implementation without braking any code outside your module. That's pretty much the whole point af getters/setters; however when using those these there's only so much optimisation you can do: any real change of implementation with inevitably make the getters much slower.
On the other hand, you can optimise the hell out of a vector-based interface, with SIMD operations, external library calls (possibly on accelerated hardware like CUDA) and suchlike. A "batch-getter" like to_posarray can still be implemented reasonably efficient, single-variable setters can't.


*I mean vector in the mathematical sense here, not like std::vector.

于 2012-12-13T06:04:14.653 に答える
4

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

于 2012-12-13T05:29:17.220 に答える
2

この質問にはさまざまな答えがあるかもしれませんが、ここで私の考えを述べます。

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

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

于 2012-12-13T05:49:23.940 に答える
0

この場合、計算の機能的な意味は次のようになります。

void Particle::updatePosition() { x += vx; y += vy; }

また:

void Particle::updatePositionX() { x += vx; }

それから :

パーティクル.updatePositionX();

于 2021-12-28T02:13:38.853 に答える