如何解决如果 operator!=() 使用 operator==() 的否定,我应该内联运算符 == 和 !=
我用这个简单的例子来说明我试图优化堆栈使用的问题。假设我有一个这样的结构:
// Something.h
struct Something {
int val;
bool operator==(const Something& rhs);
bool operator!=(const Something& rhs);
};
// Something.cpp
bool Something::operator==(const Something& rhs) {
return val == rhs.val;
}
bool Something::operator!=(const Something& rhs) {
return !(*this == rhs);
}
调用 operator!=() 会将两个堆栈帧压入堆栈(一个用于 !=,另一个用于 ==)。 我应该内联 operator!=() 以便 == 和 != 使用相同数量的堆栈吗?
解决方法
您应该使用链接时优化 (LTO),这样它们中的任何一个都可以完全内联到调用站点,尤其是当它像这样几乎微不足道时。
但是如果您不想使用 LTO 进行跨文件内联,那么将 operator !=
return !(*this == rhs);
定义放在.h
),因此每个调用者都可以看到它,并且可以将其内联到仅包含 .h
的文件中。然后调用者的 asm 将调用相同的 operator==
定义,但以相反的方式使用结果。例如test al,al
/ jnz
而不是 jz
如果您要对结果进行分支。
如果您不使用 LTO 并且不使定义对编译时内联可见,那么最好的情况是编译器会将 operator==
内联到 operator!=
独立定义中在编译那个 .cpp
时。然后你在机器代码中有两个相似大小的函数,它们只有一个布尔反转。这些函数的用户(来自其他文件)将调用其中一个,因此它们都占用了您的 I 缓存/代码占用空间。
示例
// Something.h
struct Something {
int val;
bool operator==(const Something& rhs);
bool operator!=(const Something& rhs) { return !(*this == rhs); }
};
// simulated #include for one-file demo purposes
// Some other .cpp file,operator== definition not visible.
int foo(Something &a,Something &b)
{
if (a != b) {
return a.val;
} else {
return b.val;
}
}
GCC -O3 for x86-64 (Godbolt) 编译如下:
foo(Something&,Something&):
push rbp
mov rbp,rsi
push rbx
mov rbx,rdi # save the pointers in call-preserved regs
sub rsp,8
call Something::operator==(Something const&)
test al,al # set FLAGS from the bool retval
cmovne rbx,rbp # select the right pointer
mov eax,DWORD PTR [rbx] # and load from it
add rsp,8 # epilogue
pop rbx
pop rbp
ret
请注意,这段代码调用了 Something::operator==
,它在编译时无法内联(它可以在与 LTO 的链接时内联)。如果它调用了一个实际的单独的 cmovne
,它只是使用 cmove
而不是 operator!=
。
operator!=
内联到字面上零额外成本,并且对任一函数的所有调用都使用相同的独立定义,从而节省了代码占用空间。有利于性能,尤其是当您的代码同时使用这两种运算符时,足以使其在缓存中保持热状态。
当然,当类只是一个 operator==
时,让 int
内联也会显着节省;根本不调用通常要好得多,因为不需要在某些东西周围保留寄存器。
(当然,在这种情况下,我的示例太简单了:如果它们 相等,那么它仍然可以返回 a.val
,因为它知道这与 b.val
相同。因此,如果您取消注释 Godbolt 链接中的 operator==
定义,foo
将编译为 mov eax,DWORD PTR [rdi]
/ ret
,甚至不会触及 b
。)
您对 inline
关键字的作用有误解。如需说明,请参阅此答案 https://stackoverflow.com/a/66379889/15284149
回答你的问题,是的,“内联”可能更快,这就是为什么编译器实际上会自动优化它(只要你至少有 -O1):https://godbolt.org/z/9Kn3hE
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。