问题描述
考虑使用结构 S
构造并作为参数传递给函数的示例:
struct S
{
S() {}
float vals[64];
};
inline S makeS() { return {}; }
void foo(const S &);
void bar() { foo( makeS() ); }
查看编译器生成的程序集 (https://godbolt.org/z/odoPr9836),它非常小(如预期)。
但是,如果我们从 S
中删除构造函数,从而将其转换为聚合 (https://godbolt.org/z/qEWKbx5Ps),程序集将变得庞大许多倍。
甚至似乎 MSVC 不执行强制 RVO 并复制聚合:
...
movups XMMWORD PTR [rcx-128],xmm0
movups xmm0,XMMWORD PTR [rax-96]
movups XMMWORD PTR [rcx-112],xmm1
movups xmm1,XMMWORD PTR [rax-80]
...
是否由此得出结论,与普通的 C++ 类或结构相比,在实践中使用聚合产生的最佳代码要少得多?
解决方法
你的比较是不公平的。
struct S
{
S() {}
float vals[64];
};
这样,您实际上并没有初始化 vals
。为了公平比较,它应该是:
struct S
{
S() : vals{} {}
float vals[64];
};
或者简单地使用:
S() = default;
现在 gcc 和 clang 都为它们生成相同的代码,其中 msvc 为 makeS
生成相同的代码:https://godbolt.org/z/rezxTorGs
也有人请纠正我:
struct S
{
float vals[64];
};
inline S makeS() { return {}; }
我相信这个使用默认构造函数而不是聚合初始化。
您可能需要使用 return {{}};
或 return {.vals = {}};
来强制聚合初始化。