我正在努力理解为什么我的编译器(g ++ 8.1.0和clang ++ 6.0.0)对POD(普通数据)和非POD代码的处理方式不同。
测试代码:
#include <iostream>
struct slong {
int i;
~slong() { i = 0; }
};
int get1(slong x) { return 1+x.i; }
int main() {
std::cerr << "is_pod(slong) = " << std::is_pod<slong>::value << std::endl;
}
使用析构函数(因此不是POD)定义类slong
,并且使用-Ofast的编译器将为get1生成
movl (%rdi), %eax
incl %eax
但是当我注释掉析构函数(因此slong
成为POD)时,我得到了
leal 1(%rdi), %eax
当然,性能问题较小;我还是想了解。在其他(更复杂的)情况下,我也注意到了更大的代码差异。
答案 0 :(得分:3)
请注意,movl
访问内存,而leal
不访问内存。
将struct
按值传递给函数时,如果是POD,ABI可以将其填充到寄存器(rdi
)中。
如果struct
不是POD,则ABI必须在堆栈上传递它(大概是因为代码可能需要其地址来调用析构函数,访问vtable并执行其他复杂的工作)。因此,访问其成员需要间接访问。