内嵌构件运营商VS直列运营商C ++(Inline member operators vs inli

2019-09-17 08:57发布

如果我有两个结构:

struct A
{
    float x, y;
    inline A operator*(A b) 
    {
        A out;
        out.x = x * b.x;
        out.y = y * b.y;
        return out;
    } 
}

和等效结构

struct B
{
    float x, y;
}

inline B operator*(B a, B b) 
{
    B out;
    out.x = a.x * b.x;
    out.y = a.y * b.y;
    return out;
} 

你会知道任何理由B的运营商*编译任何不同,或运行任何更慢或快于A的运营商*(即去功能内的实际行动,应该是无关的)?

我的意思是......将宣布内嵌运营商的一员,相较于未成为会员,对实际功能的速度,任何一般的效果,无论如何?

我有一个数字,目前按照联成员操作风格不同结构的......但我想修改它是有效的C代码,而不是; 所以我才这样做,我想知道是否会有性能/编译任何变化。

Answer 1:

你有它编写的方式,我期望B::operator*运行速度稍慢。 这是因为“引擎盖下”实施的A::operator*是这样的:

inline A A::operator*(A* this, A b) 
{ 
    A out;
    out.x = this->x * b.x;
    out.y = this->y * b.y;
    return out;
}

所以, A将指针传递到其左手侧参数的功能,而B拥有调用函数之前,使该参数的副本。 两者都使自己的右手边参数的副本。

您的代码会好得多,并可能会实现相同的AB ,如果你写使用引用它,并使它const正确:

struct A
{
    float x, y;
    inline A operator*(const A& b) const 
    {
        A out;
        out.x = x * b.x;
        out.y = y * b.y;
        return out;
    } 
}

struct B
{
    float x, y;
}

inline B operator*(const B& a, const B& b) 
{
    B out;
    out.x = a.x * b.x;
    out.y = a.y * b.y;
    return out;
}

你仍然希望返回对象,而不是引用,因为结果是有效的临时变量(你没有返回修改现有对象)。


附录

然而,用const传递按引用的两个参数,在B,将它使它有力的更快,由于反引用?

首先,当你拼写出所有的代码都涉及同样的间接引用。 (记住,访问成员this意味着指针引用。)

但即便如此,这取决于你的编译器是如何聪明的。 在这种情况下,让我们说这看你的结构,并决定,因为这是两个浮点数不能塞到一个寄存器,所以它会使用指针来访问它们。 所以复引用指针的情况下(这是引用得到实现)是你会得到最好的。 该组件会是这个样子(这是伪汇编代码):

// Setup for the function. Usually already done by the inlining.
r1 <- this
r2 <- &result
r3 <- &b

// Actual function.
r4 <- r1[0]
r4 <- r4 * r3[0]
r2[0] <- r4
r4 <- r1[4]
r4 <- r4 * r3[4]
r2[4] <- r4

这是假设类RISC架构(比如ARM)。 86可能使用更少的步骤,但它得到反正扩大到约由指令解码器这些细节。 问题的关键是,它的指针的所有固定偏移指针引用寄存器,这是一样快,因为它会得到。 优化器可以尝试更聪明和跨越几个寄存器执行对象,但那样的优化是困难得多写。 (虽然我有心想准是一个LLVM型的编译器/优化器能做到这一点很容易优化,如果result仅仅是未保存的临时对象。)

所以,既然你使用this ,你有一个隐含的指针引用。 但是,如果对象是在堆栈上? 没有帮助; 堆栈变量变成堆栈指针的固定偏移解除引用(或帧指针,如果使用的话)。 所以,你到底什么地方提领的指针,除非你的编译器是光明的,足以把你的对象,并在多个寄存器传播它。

随意通过-S选项gcc得到最终代码的反汇编,看看有什么你的情况真的发生了。



Answer 2:

你真的应该离开inline -ing编译器。

(这是与壳体的类定义中所定义,所述,函数A )是inline的默认值。 该inline的符A::operator *是没用的。

更有趣的情况是,当你有类定义之外成员函数定义。 在这里,如果你想提供一个提示编译器(它可以随意忽略),这是经常使用,应按说明书内嵌的范围内,主叫编译内联是必需的。

阅读C ++ FAQ 9 。



Answer 3:

这是我会怎么写的结构:

struct A
{
    float x, y;
    A(float ax, float ay) : x(ax), y(ay) { }
    A operator*(const A& b) const { return b(x * b.x, y * b.y); } 
}

要回答这个问题,是写操作的成员函数可以非常轻微快在某些情况下,但不足以使你的代码,一个明显的区别。

一些注意事项:

  1. 再也不用担心使用inline关键字。 优化编译器做什么,什么不内联自己的决定。

  2. 使用初始化构造函数。 这样做是因为它们提高代码的可读性。 睡眠好知道他们可以带来小的性能优势。

  3. 通过const引用尽可能多地通过结构。

  4. 专注于编写具有良好的作风并不快代码。 大部分代码是速度不够快,如果它是它是不是可能是因为东西在IO的算法或处理愚蠢的。



文章来源: Inline member operators vs inline operators C++