这是一个相当古老的话题:主持人和吸气者是好还是坏?
我的问题是:C++/D/Java中的编译器是否内联getter和setter?
与直接字段访问相比,getter/setter在多大程度上影响性能(函数调用,堆栈帧).除了使用它们的所有其他原因之外,我想知道除了是一个好的OOP练习之外它们是否应该影响性能.
这取决于.没有普遍的答案总是如此.
在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应该能够内联它.我不知道海湾合作委员会如何处理这个问题.
通过扩展,这也意味着如果getter是在不同的.dll/.so中定义的,则无法内联调用.
在任何情况下,我认为琐碎的获取/制定者不一定是"良好的OOP实践",或者"存在使用它们的所有其他原因".很多人认为琐碎的获取/制定者1)是设计糟糕的标志,2)浪费打字.
就个人而言,这不是我对任何一种方式都有所了解的事情.对我而言,对于有资格作为"良好的OOP实践"的东西,它必须具有一些可量化的积极效果.琐碎的获取/制定者有一些边缘优势,有些也是微不足道的缺点.因此,我不认为他们是好的或坏的做法.如果你真的想要,他们只是你可以做的事情.
在D中,所有类的方法,但不是结构,默认是虚拟的.您可以通过使方法或整个类最终来使方法非虚拟.此外,D具有属性语法,允许您创建公共字段,然后在不破坏源级兼容性的情况下将其更改为getter/setter.因此,在DI中建议只使用公共字段,除非您有充分的理由不这样做.如果你想出于某种原因使用琐碎的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; } }
我有一次完全相同的问题.
为了回答它,我编写了两个小程序:
首先:
#includeclass Test { int a; }; int main() { Test var; var.a = 4; std::cout << var.a << std::endl; return 0; }
第二:
#includeclass Test { int a; int getA() { return a; } void setA(int a_) { a=a_; } }; int main() { Test var; var.setA(4); std::cout << var.getA() << std::endl; return 0; }
我将它们编译为汇编程序,使用-O3(完全优化)并比较两个文件.他们是相同的.没有优化他们是不同的.
这是在g ++下.那么,回答你的问题:编译器可以轻松优化getter和setter.
我在Java中尝试过:使用和不使用getter和setter都是一样的.结果:两个版本的执行时间没有显着差异.这是代码:
class Person { public int age; String name; public Person(String name,int age) { this.name=name; this.age=age; } } class GetSetPerson { private int age; String name; public GetSetPerson(String name,int age) { this.name=name; this.age=age; } public void setAge(int newage) { age=newage; } public int getAge() { return age; } } class Proba { //Math.hypot kb 10-szer lassabb, mint a Math.sqrt(x*xy*y)!!! public static void main(String args[]) { long startTime, endTime, time; int i;int agevar; //Person p1=new Person("Bob",21); GetSetPerson p1=new GetSetPerson("Bob",21); startTime=System.nanoTime(); /* for (i=0;i<1000000000;i++) { p1.age++; } */ for (i=0;i<1000000000;i++) { agevar=p1.getAge(); agevar++; p1.setAge(agevar); } endTime=System.nanoTime(); time=endTime-startTime; System.out.println(""+time); System.out.println(p1.name+"'s age now is "+p1.getAge()); } }
我知道,最后鲍勃比我大一点,但为此,它应该没问题.