41

我的 C++ 项目中有一个粒子系统引擎,粒子本身只是没有函数的变量结构。目前,每个粒子 (Particle) 通过直接访问其变量从其父类 (ParticleSystem) 更新。例如

particle.x += particle.vx;

然而,我正在辩论使用这样的 getter 和 setter:

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

我的问题是:调用 getter 和 setter 是否有任何性能开销,而不是直接访问数据?

毕竟,我确实有很多粒子要更新...

4

5 回答 5

61

Setter 和 getter在未优化时会产生性能开销。 它们几乎总是在进行链接时间优化的编译器上进行优化。而在没有的编译器上,如果他们了解函数体(即不仅仅是原型),它将被优化掉。

但是,您使用 getter 和 setter 是因为您可能希望获取或设置该变量以产生额外的副作用。就像改变物体的位置一样,也会改变附近物体在物理模拟等中的位置。

最后,在优化代码的上下文中,getter 和 setter 操作的开销非常小,除非代码很热,否则不值得担心。如果它很热,只需将 getter 或 setter 移动到头文件并内联它就很容易了。

总而言之,getter 和 setter 非常值得少量或不存在的开销,因为它允许您非常具体地指定对象可以发生和不能发生的事情,并且还允许您编组任何更改。

于 2012-12-13T05:31:04.167 回答
16

我对此的看法与之前的答案不同。

getter 和 setter 表明你的类没有以有用的方式设计:如果你不从内部实现抽象外部行为,那么首先使用抽象接口是没有意义的,你不妨使用一个普通的旧结构。

想想你真正需要什么操作。这几乎肯定不是直接访问位置和动量的 x y 和 z 坐标,您宁愿将它们视为向量(至少在大多数计算中,这与优化有关)。所以你想实现一个基于向量的接口*,其中基本操作是向量加法、缩放和内积。不是按组件访问;您可能有时也需要这样做,但这可以通过单个std::array<double,3> to_posarray()成员或类似的东西来完成。

当内部组件x, y...vz无法从外部访问时,您可以安全地更改内部实现,而无需中断模块外部的任何代码。这几乎就是 getter/setter 的重点;但是,当使用这些时,您只能做很多优化:任何真正的实现更改都不可避免地会使 getter 慢得多。
另一方面,您可以通过 SIMD 操作、外部库调用(可能在 CUDA 等加速硬件上)等来优化基于向量的接口。像“batch-getter”这样的“batch-getter”to_posarray仍然可以相当有效地实现,而单变量设置器则不能。


*我在这里指的是数学意义上的向量,而不是std::vector.

于 2012-12-13T06:04:14.653 回答
4

如果 getter 和 setter 被证明是稍微复杂一点的任务,那么 getter 和 setter 可以让你的代码在未来更容易地发展。大多数 C++ 编译器都足够聪明,可以内联那些简单的方法并消除函数调用的开销。

于 2012-12-13T05:29:17.220 回答
2

这个问题可能有各种各样的答案,但我把我的想法放在这里。

对于性能,对于简单的 POD 类型,成本几乎可以忽略不计。但是还是有成本的,这取决于你返回的类型。对于粒子,不可能有太多数据。如果这是一个图像类(如 OpenCV cv::Mat)或 3d 数据(如 VTK 中的 PolyData),则 setter/getter 处理指针/迭代器比处理实际数据更好,以避免内存分配问题。

当您想要模板化事物时,setter/getter 对于避免不明确的类型转换非常有用。setter/getter 可以是访问私有/受保护成员的一种方式,这也允许您避免使用 x 作为变量的通用名称。此外,setter/getter 可以返回一个左值引用,它允许你做particle.getX() = 10.0 ;

于 2012-12-13T05:49:23.940 回答
0

在这种情况下,您的计算的功能含义可能是:

无效粒子::updatePosition() { x += vx; y += vy; }

或者:

无效粒子::updatePositionX() { x += vx; }

然后 :

粒子.updatePositionX();

于 2021-12-28T02:13:38.853 回答