TL; DR: Это сильно зависит от целевой архитектуры, компилятора и контекста, в котором вызываются функции.Если вы не уверены, профилируйте и вручную проверьте сгенерированный код.
Если функции встроены, хороший оптимизирующий компилятор, вероятно, выдаст точно такой же код в обоих случаях.
Если функции неТем не менее, указывает на то, что ABI в большинстве реализаций C ++ предписывает передавать аргумент const&
в качестве указателя.Это означает, что структура должна храниться в оперативной памяти, чтобы можно было получить ее адрес.Это может оказать значительное влияние на производительность для небольших объектов.
Давайте возьмем x86_64 Linux G ++ 8.2 в качестве примера ...
Структура с 2 членами:
struct arg
{
int a;
long b;
};
int foo1(const arg input)
{
return input.a + input.b;
}
int foo2(const arg& input)
{
return input.a + input.b;
}
Сгенерировано сборка :
foo1(arg):
lea eax, [rdi+rsi]
ret
foo2(arg const&):
mov eax, DWORD PTR [rdi]
add eax, DWORD PTR [rdi+8]
ret
Первая версия полностью передает структуру через регистры, вторая - через стек ..
Теперь давайте попробуем 3 члена :
struct arg
{
int a;
long b;
int c;
};
int foo1(const arg input)
{
return input.a + input.b + input.c;
}
int foo2(const arg& input)
{
return input.a + input.b + input.c;
}
Сгенерировано сборка :
foo1(arg):
mov eax, DWORD PTR [rsp+8]
add eax, DWORD PTR [rsp+16]
add eax, DWORD PTR [rsp+24]
ret
foo2(arg const&):
mov eax, DWORD PTR [rdi]
add eax, DWORD PTR [rdi+8]
add eax, DWORD PTR [rdi+16]
ret
Не так уж много различийхотя использование второй версии все равно будет немного медленнее, потому что для этого требуется, чтобы адрес был введен в rdi
.
Неужели так важно , что много?
Обычно нет.Если вы заботитесь о производительности определенной функции, она, вероятно, часто вызывается и поэтому составляет small .Таким образом, это, скорее всего, будет встроенный .
Давайте попробуем вызвать две функции выше:
int test(int x)
{
arg a {x, x};
return foo1(a) + foo2(a);
}
Генерируемая сборка:
test(int):
lea eax, [0+rdi*4]
ret
Вуаля.Это все спорно в настоящее время.Компилятор встроил обе функции в одну инструкцию!