将getters和setter内联制作是一种好习惯吗?

Mar*_*aux 70 c++ performance inline getter-setter

public:
     inline int GetValue() const {
          return m_nValue;
     }
     inline void SetValue(int nNewValue) {
          this -> m_nValue = nNewValue;
     }
Run Code Online (Sandbox Code Playgroud)

Learn C++上,他们表示会跑得更快.所以,我认为在getter和setter上使用它会很棒.但也许,它有一些缺点吗?

Jar*_*Par 58

在探查器明确告诉我不内联导致性能问题之前,我没有内联任何内容.

C++编译器非常智能,几乎可以自动为您自动内联这样的简单函数.通常它比你更聪明,并且会更好地确定应该或不应该内联的内容.

我会避免考虑是否内联并专注于解决方案.inline稍后添加关键字(这不是内联BTW的保证)非常容易,并且可以使用分析器轻松找到潜在的位置.

  • 如果将其实现放入单独的源文件中,编译器就无法内联.与所提供的示例无关,但值得一提. (44认同)
  • 事实上,GCC和VS都提供源文件之间的内联. (20认同)
  • @Mark - 这是真的,因为在那个阶段它实际上是链接器,而不是编译器. (7认同)
  • 如果两个文件都在同一个项目中,那么链接器可能会完成这项任务.但是,如果链接预编译的DLL,则无法内联头文件中未明确包含的任何内容. (3认同)
  • @DeadMG,我从未听说过,无法想象它将如何实施。有链接吗? (2认同)

Ara*_*raK 29

如果在定义中写入它们,则inline 默认情况下会考虑它们.

这意味着它们将被允许在多个编译单元中(因为类定义本身通常出现在多个编译单元中),而不是它们实际上将被内联.

  • 如果编译器想要内联它们...... (4认同)
  • 如果在类定义中定义函数,那么C++标准会考虑函数`inline`,这几乎与内联函数的编译器/链接器完全无关. (4认同)

Gre*_*jan 16

这是公共API中的不良做法.对这些函数的任何更改都需要重新编译所有客户端.

一般来说,getter和setter显示的是抽象不佳,不要这样做.如果您经常访问另一个类中的原始数据,那么您可能需要重新安排您的类,而不是考虑您希望如何操作类中的数据并提供适当的方法来执行此操作.

  • 超级教条的废话.您认为不需要获得字符串的长度吗?更改UI按钮上的文本?获取鼠标的当前坐标?当然,有可能滥用吸气剂和制定者,因为它适用于任何模式.但"不要这样做"作为一揽子规则是IMO糟糕的建议. (58认同)
  • @stijn:一个类应该是一个抽象的东西.它的实施应该无关紧要,其上的操作应该对它所代表的内容有意义.应该有类不变量:关于类总是正确的语句.Getter和setter几乎与公共变量一样公开实现.根据我的经验,单个变量的值在类抽象方面往往没有意义,因此您允许对类的操作与其抽象无关.吸气剂和制定者使得保持不变量变得更加困难. (7认同)
  • 你能详细说明糟糕的抽象吗?究竟是什么意思,它如何反映这个例子?m_nValue应该公开吗? (6认同)
  • 我想每个人都有一个过度敏感的反弹时刻.显然,容器具有访问器(嗯,通过引用等效):它明确地是他们纠缠特定可修改值的目的的一部分.同样很明显,大多数类都不是容器.建议"一般来说,不要这样做"的问题在于,很难使用这个建议 - 对于一个好的吸气剂/装置者的任何一个例子,回答是"我说不要一般做,不要做"当这是一个好主意时,这样做".因此,建议恰恰等同于"一般情况下,只在特定情况下做一些好主意的事情";-p (3认同)
  • @Steve:也许我们可以提出更有用的东西.这是我的建议:不要在吸气剂和制定者中进行设计.设计在抽象方面有用的函数.例如,谈论一个点的X坐标或一个字符串的长度是有道理的.如果这些本质上是吸气剂和制定者,那么这很容易实现. (3认同)
  • David Thornley说,这比我好得多。 (2认同)

Edw*_*nge 10

否定点:

  1. 编译器可以自由地忽略你.

  2. 对这些函数的任何更改都需要重新编译所有客户端.

  3. 一个好的编译器无论如何都会在适当的时候内联非内联函数.


Sha*_*ane 5

我还想补充一点,除非你每帧执行数百万次获取/设置,否则这些是否内联几乎无关紧要.老实说,不值得失眠.

另外,请记住,仅仅因为您在声明+定义前面加上"inline"一词,并不意味着编译器会内联您的代码.它使用各种启发式方法来确定它是否有意义,这通常是速度与大小的经典折衷.然而,有一个暴力的'__forceinline'关键字,至少在VC++中(我不确定它在GCC中是什么),它扼杀编译器花哨的启发式.我真的不推荐它,除了一旦你移植到不同的架构,它可能是不正确的.

尝试将所有函数定义放在实现文件中,并保留标题的纯声明(除非你是模板元编程(STL/BOOST/etc),在这种情况下,几乎所有内容都在标题中;))

人们喜欢内联的经典场所之一(至少在视频游戏中,这是我来自哪里),是数学标题.交叉/点积,矢量长度,矩阵清除等通常放在标题中,我认为这是不必要的.9/10它对性能没有影响,如果你需要做一个紧密的循环,比如用一些矩阵变换一个大的矢量数组,你可能最好手动进行数学内联,甚至更好地编码特定于平台的汇编程序.

哦,还有另外一点,如果你觉得你真的需要一个类比代码更多的数据,考虑使用好的旧结构,它不会带来抽象的OO包袱,这就是它的用途.:)

对不起,这并不意味着继续这么多,但我认为考虑现实世界的用例是有帮助的,而不是太愚蠢的编译器设置(相信我,我去过那里;))

祝好运.

巴蒂尔