Я сделал этот пример кода:
#include <vector>
struct POD {
int a;
int b;
int c;
inline static POD make_pod_with_default()
{
POD p{ 41, 51, 61 };
return p;
}
inline void change_pod_a(POD &p, int a) {
p.a = a;
}
inline void change_pod_b(POD &p, int b) {
p.b = b;
}
static POD make_pod_with_a(int a) {
POD p = make_pod_with_default();
p.change_pod_a(p, a);
return p;
}
static POD make_pod_with_b(int a) {
POD p = make_pod_with_default();
p.change_pod_b(p, a);
return p;
}
};
int main()
{
std::vector<POD> vec{};
vec.reserve(2);
vec.push_back(POD::make_pod_with_a(71));
vec.push_back(POD::make_pod_with_b(81));
return vec[0].a + vec[0].b + vec[0].c + vec[1].a + vec[1].b + vec[1].c;
}
В скомпилированном коде сборки мы видим, что следующие инструкции генерируются для первого вызова vec.push_back (...):
...
mov DWORD PTR $T2[esp+32], 41 ; 00000029H
...
mov DWORD PTR $T2[esp+36], 51 ; 00000033H
...
mov DWORD PTR $T5[esp+32], 71 ; 00000047H
...
mov DWORD PTR $T6[esp+44], 61 ; 0000003dH
...
Есть мов в [esp + 32] для 71, но мов в [esp + 32] для 41 все еще там, бесполезно!Как я могу написать код для MSVC, который обеспечит такую оптимизацию, способен ли MSVC даже на это?
И GCC, и CLANG дают более оптимизированные версии, но CLANG терпит поражение с большим запасом буквально без издержек, вочень чистый и логичный способ:
сгенерированный CLANG код:
main: # @main
push rax
mov edi, 24
call operator new(unsigned long)
mov rdi, rax
call operator delete(void*)
mov eax, 366
pop rcx
ret
Все выполняется во время компиляции, как 71 + 51 + 61 + 41 + 81 + 61 = 366!Я должен признать, что больно видеть, как моя программа вычисляется во время компиляции, и все еще бросать этот вызов vec.reserve () в сборке ... но CLANG по-прежнему отлично справляется!Давай, MSVC, это не вектор изменчивости.