Я прочитал в книге Скотта Мейерса «Эффективный C ++», что:
Когда вы встроите функцию, вы можете разрешить компилятору выполнять контекстно-зависимую оптимизацию тела функции. Такая оптимизация была бы невозможна для обычных вызовов функций.
Теперь вопрос: что такое контекстно-зависимая оптимизация и зачем она нужна?
Я не думаю, что «контекстно-зависимая оптимизация» — это определенный термин, но я думаю, что в основном это означает, что компилятор может анализировать сайт вызова и код вокруг него и использовать эту информацию для оптимизации функции.
Вот пример. Это, конечно, надумано, но оно должно продемонстрировать идею:
Функция:
int foo(int i)
{
if (i < 0) throw std::invalid_argument("");
return -i;
}
Звоните на сайт:
int bar()
{
int i = 5;
return foo(i);
}
Если foo
составляется отдельно, он должен содержать код сравнения и выдачи исключений. Если это встроено в bar
, компилятор видит этот код:
int bar()
{
int i = 5;
if (i < 0) throw std::invalid_argument("");
return -i;
}
Любой вменяемый оптимизатор оценит это как
int bar()
{
return -5;
}
Если компиляция решит встроить функцию, она заменит вызов функции этой функции телом функции. Теперь у него есть больше кода для оптимизации внутри тела функции вызывающей стороны. Поэтому это часто приводит к лучшему коду.
Представь это:
bool callee(bool a){
if(a) return false;
else return true;
}
void caller(){
if(callee(true)){
//Do something
}
//Do something
}
После включения код будет выглядеть примерно так:
void caller(){
bool a = true;
bool ret;
if(a) ret = false;
else ret = true;
if(ret){
//Do something
}
//Do something
}
Что может быть оптимизировано и дальше:
void caller(){
if(false){
//Do something
}
//Do something
}
А затем:
void caller(){
//Do something
}
Функция теперь намного меньше, и у вас нет затрат на вызов функции и особенно (в отношении вопроса) стоимость ветвления.
Скажи, что функция
void fun( bool b) { if(b) do_sth1(); else do_sth2(); }
и это называется в контексте с предопределенным false
параметр
bool param = false;
...
fun( param);
тогда компилятор может уменьшить тело функции до
...
do_sth2();
Я не думаю что контекстная оптимизация означает что-то конкретное, и вы, вероятно, не можете найти точное определение.
Хорошим примером будет классический метод получения некоторых атрибутов класса, без включения в него программы:
eax
на x86
под окнами с настройками Visual Studio по умолчанию)eax
к локальной переменнойПри использовании встраивания можно пропустить практически всю работу и переместить значение непосредственно в локальную переменную.
Оптимизация строго зависит от компилятора, но многое может произойти (распределение переменных может быть пропущено, код может изменить порядок и т. Д.). Но вы всегда сохраняете call / jump, что является дорогостоящей инструкцией.
Больше чтения по оптимизации Вот.