定义流畅的界面是否会影响性能?

时间:2011-02-04 15:55:32

标签: c++ fluent-interface

我刚看了this question,这为我提出了另一个问题:

考虑这个课程:

class Foo
{
public:
  void setA(int a) { m_a = a; }
  void setB(int b) { m_b = b; }
private:
  int m_a, m_b;
};

也可以使用“流畅的界面”方法编写:

class Foo
{
public:
  Foo& setA(int a) { m_a = a; return *this; }
  Foo& setB(int b) { m_b = b; return *this; }
private:
  int m_a, m_b;
};

现在,如果我编写以下代码片段:

int main()
{
  Foo foo;
  foo.setA(1);
  foo.setB(2);
}

如果我使用类的第二个实现,是否会有额外的return指令引起的性能差异?

我应该打扰吗? (我的猜测是“不”)

6 个答案:

答案 0 :(得分:4)

  

如果我使用类的第二个实现,是否存在由附加返回指令引起的性能差异?

我不知道,您的编译器和优化器设置是否存在?在你给出的确切情况下,我没有看到任何阻止任何开销被优化的东西,但我可以想象为一个没有优化这种情况的深奥平台编写一个天真的,次优的编译器。

如果您认为在特定情况下这很重要,test it instead of assuming

答案 1 :(得分:0)

我认为由于编译器优化没有区别。

答案 2 :(得分:0)

如果使用第二个实现并且不需要set函数的返回值,则最好写为

  (void) foo.setA(1);
  (void) foo.setB(2);

这样编译器或静态分析器就不会抱怨没有使用返回值。

至于性能,与第一个实现相比,返回引用可能(我不确定)生成一个/两个额外的汇编指令,但可能没有任何“真正的”差异。

答案 3 :(得分:0)

由于这些方法是内联的,编译器应该能够看到返回值未被使用并可能将其优化掉。

使用对您的项目设计最有意义的方式。然后,测量性能,只有当它不够好时才会考虑优化代码。

答案 4 :(得分:0)

根据您定义类的方式,您将看不到两者之间的差异(如果有的话)。但是,如果你稍微修改一下你的设计,你会:

class Foo1
{
public:
    Foo1(int a, int b) : m_a(a), m_b(b) {}
    void setA(int a) { m_a = a; }
    void setB(int b) { m_b = b; }
private:
    int m_a, m_b;
};

class Foo2
{
public:
    Foo& setA(int a) { m_a = a;  return *this; }
    Foo& setB(int b) { m_b = b;  return *this; }
private:
    int m_a, m_b;
};

初始化Foo1

Foo1 f(1, 2); // only constructor called

将比初始化Foo2

更有效率
Foo2 b; // constructor called
b.setA(1).setB(2); // 2 functions called

在某些情况下,这不会引起关注。

您对Fluent Interfaces的另一个顾虑是最终用户错误地使用它们的能力。在设计界面时,您需要对其进行设计,以使界面用户很难将其破坏。通过从每个setter返回一个引用,如果用户代码存储了该引用,然后该对象被移动或取消分配,那么你有一个悬空引用(甚至可能没有实现它)。

答案 5 :(得分:0)

这些性能差异从来都不重要。但是,证明我对一些实际应用的测量是错误的。