定义流畅的界面会对性能产生影响吗?

发布于 2024-10-16 01:45:57 字数 669 浏览 5 评论 0原文

我刚刚读了这个问题,这给我提出了另一个问题:

考虑这个类:

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 指令是否会导致性能差异?

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

I just read this question, which raises for me another question:

Consider this class:

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

Which could also be written using the "fluent interface" method:

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;
};

Now, if I write the following code snippet:

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

Is there a performance difference induced by the additional return directives if I use the second implementation of the class ?

Should I bother ? (My guess is "no")

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

墨落画卷 2024-10-23 01:45:57

如果我使用该类的第二个实现,附加返回指令是否会导致性能差异?

不知道你的编译器和优化器设置有没有?我认为没有什么可以阻止在您给出的确切情况下优化任何开销,但我可以想象为一个没有优化这种情况的深奥平台编写一个幼稚的、次优的编译器。

如果您认为它在特定情况下很重要,请测试它而不是假设

Is there a performance difference induced by the additional return directives if I use the second implementation of the class?

I don't know, is there with your compiler and optimizer settings? I see nothing that prevents any overhead from being optimized away in the exact case you give, but I can imagine writing a naive, sub-optimal compiler for an esoteric platform which did not optimize this case.

If you think it matters in a given situation, test it instead of assuming.

大姐,你呐 2024-10-23 01:45:57

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

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

Since the methods are inlined, the compiler should be able to see that the return value is unused and possibly optimize it away.

Use whichever way makes the most sense for your project design. Then, measure the performance and only if it's not good enough would you consider optimizing the code.

蓬勃野心 2024-10-23 01:45:57

我认为由于编译器优化,不会有任何差异。

I think there will be no difference due to compiler optimization.

渔村楼浪 2024-10-23 01:45:57

如果使用第二种实现并且不需要设置函数的返回值,那么最好编写为这样

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

,以便编译器或静态分析器不会抱怨未使用返回值。

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

If the 2nd implementation is used and the return value of the set functions are not required, then it may be better to write as

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

so that the compiler or static analyzer does not complain that the return value is not used.

As for performance, returning the reference may (I am not sure) generate one/two additional assembly instructions compared to the 1st implementation, but may not any "real" difference.

颜漓半夏 2024-10-23 01:45:57

通过定义类的方式,您不会发现两者之间有太大差异(如果有的话)。但是,如果您稍微修改一下设计,您将:

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 返回一个引用,如果用户代码存储该引用,然后移动或释放该对象,则您将拥有一个悬空引用(甚至可能没有意识到)。

With the way you've defined the classes, you won't see much of a difference (if any) between the two. However, if you fix your design a bit, you will:

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;
};

Initializing Foo1:

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

will be far more efficient than initializing Foo2:

Foo2 b; // constructor called
b.setA(1).setB(2); // 2 functions called

In some cases, that won't be a concern.

An additional concern you have with Fluent Interfaces is the ability for the end-user to use them incorrectly. When designing an interface, you want to design it so that it is very difficult for the user of your interface to break it. By returning a reference from every setter, if the user-code stored that reference and then the object is moved or deallocated, you have a dangling reference (and may not even realize it).

故事未完 2024-10-23 01:45:57

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

Those kinds of performance differences are never important. But, prove me wrong with some measurements of a real application.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文