Вопрос

Я знаю, что могу передать указатель на функцию в качестве параметра шаблона и получить к нему встроенный вызов, но мне было интересно, могут ли какие-либо компиляторы в наши дни встроить «очевидную» встроенную функцию, например:

inline static void Print()
{
 std::cout << "Hello\n";
}

....

void (*func)() = Print;

func();

В Visual Studio 2008 он достаточно умен, чтобы свести его к инструкции прямого вызова, поэтому кажется позором, что он не может пойти дальше?

Это было полезно?

Решение

GNU g++ 4.5 встраивает его для меня, начиная с уровня оптимизации -O1.

main:
    subq    $8, %rsp
    movl    $6, %edx
    movl    $.LC0, %esi
    movl    $_ZSt4cout, %edi
    call    _ZSt16__ostream_insertIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_E
    movl    $0, %eax
    addq    $8, %rsp
    ret

где .LC0 — это .string «Hello ».

Для сравнения: без оптимизации g++ -O0 он не встраивался:

main:
    pushq   %rbp
    movq    %rsp, %rbp
    subq    $16, %rsp
    movq    $_ZL5Printv, -8(%rbp)
    movq    -8(%rbp), %rax
    call    *%rax
    movl    $0, %eax
    leave
    ret

Другие советы

В новых версиях GCC (4.4 и выше) есть опция -findirect-inlining.Если GCC может доказать себе, что указатель функции является константой, он выполняет прямой вызов функции или полностью встраивает функцию.

Ну, компилятор на самом деле не знает, будет ли эта переменная где-то перезаписана или нет (может быть, в другом потоке?), поэтому он допускает ошибку и реализует ее как вызов функции.

Я только что проверил VS2010 в выпускной сборке, и она не была встроена.

Кстати, вы украшаете функцию как inline бесполезно.Стандарт гласит, что если вы когда-нибудь получите адрес функции, любой inline подсказка будет проигнорирована.

редактировать:однако обратите внимание, что, хотя ваша функция не была встроена, переменная исчезла.В процессе разборки call использует прямой адрес, он не загружает переменную в регистр и не вызывает ее.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top