【问题标题】:In OOP, is it faster to call a function to return a value, or by directly calling the value?在OOP中,是调用函数返回值还是直接调用值更快?
【发布时间】:2018-04-17 16:21:43
【问题描述】:

如果我有课File

class File {
    public:
        File(int length);
        getLength();  //returns length int value
        int length;
}

File.value(暗示它不是私有的/其他任何东西,因此可以直接访问)和File.getValue()之间,哪个选项对性能影响较小?

【问题讨论】:

  • 我们不要考虑速度,而是考虑封装。我应该能够直接访问length 吗?如果是这样,则根本没有理由拥有吸气剂。如果我不应该使用吸气剂。
  • @arrowd a)它不会在任何半体面的编译器上。 b) 考虑这种微优化是适得其反的缩影
  • 如果函数的主体是{ return length; } 并且编译器无法优化它,我也不相信它会优化任何其他代码。
  • 优化器完成后,对我来说看起来差不多。除非我做愚蠢的事情,否则带有 -O3 的 GCC 4.8 到 7.3 的样本都会为两者提供mov edi, DWORD PTR [rdi]
  • 封装点远比速度重要。如果最终用户可以更改length 并对您的代码产生负面影响,那么它有多快并不重要。有人会打破它。然后责怪你。

标签: c++ oop object


【解决方案1】:

如果不进行优化,getter 会花费更多。一个值可以通过一条 'mov' 指令访问,但函数调用(用于 getter)将需要更多指令(至少额外的 'call' 和 'ret')。

如果您将 getter 定义为“内联”,那么大多数编译器将删除函数调用,其性能将与直接访问成员变量相同。 'inline' 方法和函数很可能会在头文件中实现(因为每个翻译单元都需要访问函数源)。

如果启用优化,大多数现代编译器甚至会内联未标记为“内联”的 getter。一些编译器会在线删除来自同一模块(.cpp 文件)中的调用的函数调用。至少 Visual C++ 会删除函数调用,即使它是从另一个模块或项目调用的,如果“链接时间代码生成”(LTCG) 对这两个部分都处于活动状态。

注意:即使现代编译器不使用“inline”关键字来决定是否应内联方法,它仍然可以避免在头文件中实现方法时通常会出现的“多重定义”链接器错误从多个模块中使用。

如果您可以公开访问成员变量,则很有可能根本不需要 getter(和/或 setter)。

【讨论】:

  • "'inline' 方法和函数必须在头文件中实现" - 不,这是不正确的。 inline 函数可以在头文件之外实现 - 还要记住 LTO 是一回事,就优化而言,inline 无论如何都被现代编译器忽略了;他们将根据自己的分析而不是 inline 关键字进行内联或不内联。
  • 你是对的。如果您必须从多个模块中使用它是有道理的,但请确保您可以从模块中声明一个内联函数。我认为 LTO 是 Visual C++ 中 LTCG 的(一部分)。
  • inline 不是为了优化,而是为了允许多个相同的定义,所以编译器会有源代码,因此 可能 内联。 LTO 消除了对它的需要,除了在仅标头库中使用。
  • 最初的意图是将其用作编译器/优化器的提示,即“首选函数的内联替换 [...]”。即使现代编译器自行决定,至少在 Visual C++ 中它仍然可以达到此目的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多