吸气剂和二传手.有性能开销吗?

sgt*_*ale 35 c++ performance getter-setter

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

particle.x += particle.vx;
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

Omn*_*ity 49

未经优化后, Setter和getter会产生性能开销. 它们几乎总是在进行链接时间优化的编译器上进行优化.对于那些没有的编译器,如果他们对功能体有所了解(即不仅仅是原型),它将被优化出来.

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

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

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

  • 但请务必记住,内联函数是a)只是一个建议,而b)仅在源文件具有所有可用信息时才起作用,因此它必须在标题中. (6认同)
  • 关于"微不足道"和"微不足道"的评论:函数调用成本周期,并且在科学计算中(在大型,长期运行的循环中发生大量获取/集合),如果不是,它们可能会花费大量(墙)时间优化了.也就是说,内联getter/setter通常是未来代码灵活性的好主意. (6认同)
  • 内联+1(虽然其余部分也是现货).内联并忘记. (4认同)
  • @TonyK.我同意可能需要它,但它往往不是.好点虽然它可以加起来.始终使用分析来确定代码中的热点.并根据需要进行优化. (2认同)
  • @马修M。我们知道,今天的 CPU 不进行指令管道重新排序,因为此类技术需要使用神经凝胶包。哎呀,等等。他们是这样。因此,您精心优化的汇编代码就消失了,这意味着您*仍然*受到优化器的支配。此外,编译器*可能*比OP更了解汇编语言。 (2认同)
  • @OmnipotentEntity:在最近的编译器中,内联可以在链接时完成,这意味着即使函数的定义在实现文件中而不是在头文件中,也可以内联函数.*编辑*:哦等等,我只是看到你是答案的作者!由于您在答案中唤起了链接时优化,因此只有在定义位于标题中时,我才能理解您关于内联的评论. (2认同)
  • @LucTouraille,在最近的编译器上,当然。我知道 clang 有链接时间优化,但你必须指定 `-O4`,iirc。gcc 具有链接时间优化,但您必须使用“-flto”专门请求它,因为“-O3”不这样做。不确定 MSVC。 (2认同)

lef*_*out 14

我对此有不同的看法,而不是之前的答案.

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

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

当内部组件x,y... vz从外面无法访问,您就可以放心地改变内部实现无制动的模块之外的任何代码.这几乎是getter/setter的重点; 然而,当使用这些时,你可以做的只有那么多的优化:任何真正的实现改变都不可避免地使得getter慢得多.
另一方面,您可以通过SIMD操作,外部库调用(可能在CUDA等加速硬件上)等来优化基于矢量的界面.像"批量获取者"一样to_posarray仍然可以合理有效地实现,单变量设置者不能.


*我的意思是数学意义上的向量,而不是像std::vector.