getter 和 setters 是否会影响 C++/D/Java 中的性能?

2022-09-01 06:42:20

这是一个相当古老的话题:设置者和获取者是好是坏?

我在这里的问题是:C++ / D / Java内联编译器的getters和setter吗?

与直接字段访问相比,getters/setters 在多大程度上影响性能(函数调用,堆栈帧)。除了使用它们的所有其他原因之外,我想知道除了作为一个好的OOP实践之外,它们是否应该影响性能。


答案 1

这要视情况而定。没有一个普遍的答案总是正确的。

在Java中,JIT编译器迟会将其内联。据我所知,JVM JIT 编译器只优化了大量使用的代码,因此您最初可以看到函数调用开销,直到 getter/setter 被足够频繁地调用。

在C++中,它几乎肯定会被内联(假设启用了优化)。但是,有一种情况可能不会:

// foo.h
class Foo {
private:
  int bar_;

public:
  int bar(); // getter
};

// foo.cpp
#include "foo.h"

int Foo::bar(){
  return bar_;
}

如果函数的定义对类的用户不可见(它将包括 foo.h,但看不到 foo.cpp),则编译器可能无法内联函数调用。

如果启用了链接时代码生成作为优化,MSVC 应该能够将其内联。我不知道GCC如何处理这个问题。

通过扩展,这也意味着如果 getter 是在不同的 .dll/.so 中定义的,则调用不能内联。

无论如何,我不认为琐碎的获取/setter一定是“良好的OOP实践”,或者“使用它们的所有其他原因”。很多人认为琐碎的get/setters1)是糟糕设计的标志,2)浪费打字。

就我个人而言,无论哪种方式,我都不会为此而烦恼。对我来说,要使某些东西有资格成为“良好的OOP实践”,它必须具有一些可量化的积极影响。琐碎的获取/设置者有一些边际优势,有些同样微不足道的劣势。因此,我不认为它们是好或坏的做法。如果你真的想,它们只是你可以做的事情。


答案 2

在 D 中,默认情况下,类的所有方法(而不是结构)都是虚拟的。您可以通过使方法或整个类成为最终方法,使该方法成为非虚拟方法。此外,D 具有属性语法,允许您将某些内容设置为公共字段,然后在以后将其更改为 getter/setter,而不会破坏源代码级兼容性。因此,在D中,我建议只使用公共字段,除非你有充分的理由这样做。如果出于某种原因想要使用琐碎的 getter/setter,例如只有一个 getter 并使变量从类外部读,请使它们成为 final。


编辑:例如,以下行:

S s;
s.foo = s.bar + 1;

将适用于两者

struct S
{
     int foo;
     int bar;
}

struct S
{
     void foo(int) { ... }
     int bar() { ... return something; }
}

推荐