Какая из 2 функций по скорости выполнения будет быстрее и почему?
Есть вот такие 2 функции:
1.
#include <iostream>
int ReturnIntX(int x) {
if (x == 1) {
return x;
}
}
int main()
{
int a = 1;
int b = ReturnIntX(a);
}
#include <iostream>
int ReturnInt1(int x) {
if (x == 1) {
return 1;
}
}
int main()
{
int a = 1;
int b = ReturnInt1(a);
}
Имеет ли вляиние на это предыдущий запуск/фоновые процессы?
Мне интересно узнать, что будет быстрее: возвращение переданного аргумента, или литеральное значение? Ведь если так подумать, что переменная x, хоть и пустая может иметь "вес", а если ещё и значения, то "вес" увеличивается
P.s.: Могли бы подсказать библиотеки для самостоятельной проверки?
Ответы (3 шт):
Если функция ReturnIntX
получает аргумент x
не равный единице, выполнение функции завершится без возврата значения. Язык C++ считает такую ситуацию неопределённым поведением. Компилятор предполагает что программист не допускает неопределённого поведения. То есть, фактически компилятор предполагает что x
всегда будет передан в функцию со значением равным единице. А тогда можно сделать оптимизацию и вернуть из функции единицу, а условный оператор удалить. Более того, можно удалить и вызов функции, так как результат её выполнения известен заранее. Что компилятор и делает: все вызовы функции в коде заменяются на литеральное значение - единицу.
Это верно для обоих вариантов функции и делает ваш вопрос бессодержательным: кода функции в программе нет, интересоваться скоростью её работы бессмысленно.
P.S. Скорость работы функции вообще условность. Вы можете измерять скорость работы программы целиком и по этой скорости делать вывод о "скорости функции". Но "скорость функции" в другой программе может проявиться по-другому. Требуется большой опыт чтобы определить надежно "скорость функции".
Современные компиляторы давно уже не компилируют ваш код построчно. Задача компилятора — найти самый эффективный код, который будет вести себя так же, как и ваш исходник.
Поскольку в вашем случае (отвлекаясь от UB) смысл обоих фрагментов одинаковый, то и компилироваться он будет одинаково. Как именно — зависит от конкретного компилятора, а также от целевой платформы.
Вот например, для интеловской платформы clang произвёл одинаковый код: https://godbolt.org/z/EPKqxKP75:
mov eax, 1
cmp edi, 1
je .EXIT
Компилятор вообще имеет право менять ваш код как угодно, только бы результат был таким же (за вычетом UB). Вот тут он, например, свернул цикл в обычное умножение.
Если вы хотите оптимизировать код, то не стоит заботиться о подобных нанооптимизациях, компилятор умеет это делать намного лучше вас. Оптимизируйте алгоритмы и структуры данных, которые вы используете.
В случае натягивания абстрактной совы на виртуальный глобус ответить на этот вопрос невозможно.
Например, в данном конкретном случае функция будет эквивалентна return 1;
из-за неопределённого поведения, и, возможно, после подстановки вообще уйдет из кода, просто где-то в регистр запишется единица.
В теории все зависит от того как из вашего буквального значения (литерального?) получается итоговый объект и насколько это "дороже" копирования, и насколько возможно подстановка. в случае исправленного кода.
Однако насколько RVO быстрее копирования заранее сказать нельзя. Можно только гарантировать, что NRVO на аргументы функции не распространяется, поэтому в не-consteval контексте не-ссылочный аргумент всегда будет скопирован, а не создан "на месте".
Остальное могут сказать только замеры производительности или чтение кода, созданного компилятором для конкретной ситуации.