这是一个相当古老的话题: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方法无助于解决问题。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top