我刚看了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
指令引起的性能差异?
我应该打扰吗? (我的猜测是“不”)
答案 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)
这些性能差异从来都不重要。但是,证明我对一些实际应用的测量是错误的。