如果我有两个结构:
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代码,而不是; 所以我才这样做,我想知道是否会有性能/编译任何变化。
你有它编写的方式,我期望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
拥有调用函数之前,使该参数的副本。 两者都使自己的右手边参数的副本。
您的代码会好得多,并可能会实现相同的A
和B
,如果你写使用引用它,并使它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
得到最终代码的反汇编,看看有什么你的情况真的发生了。
你真的应该离开inline
-ing编译器。
(这是与壳体的类定义中所定义,所述,函数A
)是inline
的默认值。 该inline
的符A::operator *
是没用的。
更有趣的情况是,当你有类定义之外成员函数定义。 在这里,如果你想提供一个提示编译器(它可以随意忽略),这是经常使用,应按说明书内嵌的范围内,主叫编译内联是必需的。
阅读C ++ FAQ 9 。
这是我会怎么写的结构:
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); }
}
要回答这个问题,是写操作的成员函数可以非常轻微快在某些情况下,但不足以使你的代码,一个明显的区别。
一些注意事项:
再也不用担心使用inline关键字。 优化编译器做什么,什么不内联自己的决定。
使用初始化构造函数。 这样做是因为它们提高代码的可读性。 睡眠好知道他们可以带来小的性能优势。
通过const引用尽可能多地通过结构。
专注于编写具有良好的作风并不快代码。 大部分代码是速度不够快,如果它是它是不是可能是因为东西在IO的算法或处理愚蠢的。