getter 和 setter 会影响 C++/D/Java 中的性能吗?
题
这是一个相当古老的话题:setter 和 getter 是善还是恶?
我的问题是:C ++ / D / Java中的编译器是否插入了Getters和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应该能够内嵌它。我不知道GCC是如何处理的问题。
通过扩展,这也意味着,如果吸气剂是在不同的.dll定义/。所以,该呼叫的可以不被内联。
在任何情况下,我不认为简单的get / setter方法必然是“好面向对象编程惯例”,或有“所有其他原因使用它们”。很多人认为简单的get / setter方法:1)是糟糕的设计标志,和2)是打字的浪费。
个人而言,这不是我的工作得到了有关两种方式。在我看来,对于一些有资格作为“良好的面向对象编程惯例”,它必须有一些量化的积极影响。简单的get / setter方法有一定的边际优势,有的只是微不足道的缺点。因此,我不认为他们是好还是不好的做法。他们只是一些你可以做,如果你真的想。
其他提示
在d中,类的所有方法,但不是结构,在默认情况下虚拟的。你可以做一个方法非虚通过使任何方法或全班最后。此外,d具有属性的语法,可以让你做一些公共字段,然后将其更改为一个getter / setter方法后不会破坏源代码级兼容。因此,在d我只想用公共领域,除非你有一个很好的理由不这样做推荐。如果你想用琐碎的getter / setter方法由于某种原因,例如仅具有一个getter和只读从类的外部进行变量,使他们最终的决定。
编辑:例如,行:
S s;
s.foo = s.bar + 1;
将两个工作
struct S
{
int foo;
int bar;
}
和
struct S
{
void foo(int) { ... }
int bar() { ... return something; }
}
我试过在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());
}
}
我知道,在年底鲍勃比我大了一点,但对于这一点,应该没问题。
我有完全相同的问题一次。
要的answere它予编程两个小程序:
第一
#include <iostream>
class Test
{
int a;
};
int main()
{
Test var;
var.a = 4;
std::cout << var.a << std::endl;
return 0;
}
第二
#include <iostream>
class 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(完全优化) 比较这两个文件。他们是相同的。 如果没有优化他们是不同的。
这是下克++。 因此,要的answere你的问题:编译器轻松优化getter和setter了
任何JVM(或编译器)值得其盐需要支持内联。在C ++中,编译器内联的getter和setter。在Java中,JVM内联它们在运行时后,他们被称为“足够”的时间。我不知道d。
根据的预期发展类,GET / setter方法可能会弄乱你的代码与让您灵活扩展您的实现,而不会影响客户端代码。
我常常遇到被用作“数据容器”,同时具有getter和setter为每个成员的类。这是无稽之谈。如果你不希望需要一些“特殊”功能获取或设置一个成员时被触发了,不写了。
考虑到机器的速度,书写额外的抽象的努力将花费你的客户更多的钱。
大多数编译器能够优化琐碎的getter / setter方法,但只要你声明它们的虚拟(以C ++),你支付额外的查找 - 常值得的。
将需要在某些情况下,某些成员的吸气。但是提供一个getter和setter一类的每个数据成员是不是一个好的做法。这样做将是类的接口复杂化。还制定者会带来资源的所有权问题,如果不妥善处理。
引用自 这里 关于 D 编程语言
我认为 DMD 目前无法对虚拟 getter 和 setter 进行去虚拟化。虚拟调用本身有点慢,但它们也不允许内联,因此无法完成连续的标准优化。因此,如果对属性的此类访问是虚拟调用,并且这种情况发生在代码的“热门”部分,那么它可能会显着减慢您的代码速度。(如果它发生在代码的非热门部分,通常不会产生任何影响。这就是为什么 Java Hot Spot 不需要优化所有代码来生成非常快的程序)。
我曾鼓励过 Frits van Bommel 提高 LDC 的去虚拟化能力:
现在,LDC 能够在少数非常简单的情况下做到这一点,但大多数情况下,与 DMD 相比,情况没有变化。最终LLVM会改进,所以这种情况可以自行改善。但前端也可以对此做一些事情。
在C ++中,当一个编译器的优化被启用,则getter和setter可以“内联”:即,使用相同的机器指令,因为将用于直接访问底层构件数据来实现
我将回声Xtofl。
getter和setter方法是那些有时有用的东西之一,但如果你把这些教条的人谁不知何故从飞跃“已被证明在某些情况下非常有用”到“必须使用所有的时间,如果你不使用它你是谁应该被杀死”异教徒。
如果您有副作用于获取或设置,通过各种手段使用一个getter和setter方法。
但如果不是,写getter和setter只是杂波了代码。有一个小的性能损失。在Java中,如果它只是执行了几次,在perforance点球不应该的问题,如果它的经常执行,它应该被内联这样的刑罚减轻。所以我更担心使得代码难以阅读。
不要一分钟购买,这消除了全局数据的问题的争论。全局数据是不好的,应当避免。但在宣布成员字段私下再创造公共getter和setter方法无助于解决问题。