c++ - 内联成员运算符与内联运算符 C++

标签 c++ performance struct inline operator-keyword

如果我有两个结构:

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 的 operator* 与 A 的 operator* 相比有任何不同的编译方式或运行得更慢或更快的原因(函数内部进行的实际操作应该无关紧要)?

我的意思是...将内联运算符声明为成员,而不是声明为成员,对实际函数的速度有任何一般影响吗?

我有许多不同的结构,它们目前都遵循内联成员运算符风格……但我想改为将其修改为有效的 C 代码;所以在我这样做之前,我想知道性能/编译是否会有任何变化。

最佳答案

按照您编写的方式,我希望 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;
}

您仍然希望返回对象,而不是引用,因为结果实际上是临时的(您不会返回修改后的现有对象)。


附录

However, with the const pass-by-reference for both arguments, in B, would it make it effectively faster than A, due to the dereferencing?

首先,当您拼出所有代码时,两者都涉及相同的解除引用。 (请记住,访问 this 的成员意味着指针取消引用。)

但即便如此,这也取决于您的编译器的智能程度。在这种情况下,假设它查看了您的结构并决定不能将其填充到寄存器中,因为它是两个 float ,因此它将使用指针来访问它们。因此,解除引用的指针情况(这是实现引用的方式)是您将获得的最好的情况。程序集看起来像这样(这是伪汇编代码):

// 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)。 x86 可能使用更少的步骤,但无论如何它都会被指令解码器扩展到这个细节级别。关键是它是寄存器中指针的所有固定偏移量取消引用,这与它所能达到的速度差不多。优化器可以尝试变得更聪明并跨多个寄存器实现对象,但这种优化器更难编写。 (尽管我暗暗怀疑,如果 result 只是一个未保留的临时对象,LLVM 类型的编译器/优化器可以轻松地进行优化。)

因此,由于您正在使用 this,因此您有一个隐式指针取消引用。但是如果对象在堆栈上呢?没有帮助;堆栈变量变成堆栈指针(或帧指针,如果使用)的固定偏移取消引用。因此,除非您的编译器足够聪明,可以获取您的对象并将其分布在多个寄存器中,否则您最终会在某处取消引用指针。

随意将 -S 选项传递给 gcc 以获得最终代码的反汇编,以查看您的案例中到底发生了什么。

关于c++ - 内联成员运算符与内联运算符 C++,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10670560/

相关文章:

c++ - 错误 : "expected class name"

java - jdbcexecuteBatch 与使用大查询执行

c++ - "array bound is not an integer constant"在运行时创建结构

c++ - 对如何初始化类成员感到困惑

c++ - 如何使用Boost ASIO实现IPC协议(protocol)?

java - 如何减少或消除从按钮单击启动 Android Activity 的延迟

c++ - 任何程序都会检测到 C/C++ 结构中的缓冲区溢出吗?

c - 在非结构或 union 中请求成员 `type'

C++ 模板,即使没有显式类实例化,仍然能够使用类方法

java - 重数计算的最佳有效解决方案?