POD 和非 POD 之间的性能差异 类
Performance difference between POD and non-POD classes
我很难理解为什么我的编译器(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)的 class slong
并且带有 -Ofast 的编译器将为 get1
生成
movl (%rdi), %eax
incl %eax
但是当我注释掉析构函数时(所以 slong
变成 POD)我得到
leal 1(%rdi), %eax
当然,性能问题是次要的;我还是想明白。在其他(更复杂的)情况下,我还注意到更重要的代码差异。
请注意 movl
会访问内存,而 leal
不会。
当按值将 struct
传递给函数时,如果它是 POD,ABI 可以将其填充到寄存器 (rdi
) 中。
如果 struct
不是 POD,ABI 必须将它传递到堆栈上(大概是因为代码可能需要它的地址来调用析构函数、访问 vtable 和做其他复杂的事情)。所以访问它的成员需要间接访问。
我很难理解为什么我的编译器(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)的 class slong
并且带有 -Ofast 的编译器将为 get1
movl (%rdi), %eax
incl %eax
但是当我注释掉析构函数时(所以 slong
变成 POD)我得到
leal 1(%rdi), %eax
当然,性能问题是次要的;我还是想明白。在其他(更复杂的)情况下,我还注意到更重要的代码差异。
请注意 movl
会访问内存,而 leal
不会。
当按值将 struct
传递给函数时,如果它是 POD,ABI 可以将其填充到寄存器 (rdi
) 中。
如果 struct
不是 POD,ABI 必须将它传递到堆栈上(大概是因为代码可能需要它的地址来调用析构函数、访问 vtable 和做其他复杂的事情)。所以访问它的成员需要间接访问。