Owszem. Jakaś prosta funkcja, której nie opłaca się wywoływać (np. w pętli) zostanie przeniesiona w miejsce wywołania. Przykładowo:
bool wieksze( int a, int b ) { return a > b; } int main() { for( int i = 0; i <= 10; i++ ) { wieksze( i, 5 ); } }
Tutaj jest pętla. Wywołanie funkcji oznacza chwilowe zawieszenie main() i przeniesienie wykonywania programu do innego miejsca. To zajmuje czas. Pętla zwalnia, program zwalnia. Zatem najlepiej byłoby przenieść kod do pętli i tak na 98% zrobi kompilator pomimo nieumieszczenia specyfikatora inline.
inline obsługuje kompilator. Niemożliwym jest zatem, aby to umieszczanie w miejscu wywołania miało miejsce w czasie działania programu. Działanie programu to wykonywanie jego kodu. Nie można wtedy nic mieszać w jego strukturze. Kompilator działa tylko w czasie kompilacji i to właśnie wtedy wywołania podmieniane są na ciało funkcji (identycznie jak przy #define).
Nie istnieje jedna funkcja, którą raz się opłaca dawać inline, a raz nie. Jeśli jest to krótka funkcja (jak w moim przykładzie powyżej), która będzie wywoływana tysiące razy, to może się okazać, że kod generowany z obsługą wywołania funkcji i powrotem zajmie więcej pamięci niż wklejenie jej ciała 1000 razy gdzieś w kodzie. Jeśli funkcja jest spora, to nigdy nie opłaca Ci się dawać jej inline. Jeśli wywołujesz tysiące razy jakąś dużą funkcję, to również. Trudno. Program zwolni o 0,0001 s. Musisz to przeboleć.
Pamiętaj też, że wypisywanie czegokolwiek na ekran, czy to przy po mocy cout <<, czy printf(), to również są wywołania funkcji i przeskoki w inne miejsca. Musisz zdać sobie sprawę, że prawie wszystko co robisz w kodzie, to wywołanie jakiejś funkcji. Nawet zwykłe utworzenie string:
string napis = "Ala";
Wywołujesz funkcję z argumentem const char* "Ala"
Konstruktory i destruktory tak samo jak inne funkcje mogą stać się inline. Choć o tym najpewniej zadecyduje sam kompilator. Więc nie ma z tym problemu.
Ciekawszym tematem są funkcje wirtualne, które również mogą być inline. I nie, to nie jest przejęzyczenie. Nie rujnuje to zasad działania polimorfizmu, bo kompilator sobie z tym radzi w ciekawy sposób. Nie chcę się tutaj rozwodzić za bardzo, ale w skrócie napiszę: Kompilator rozpoznaje kiedy wywoływana jest funkcja rodzica, a kiedy potomka i dzięki temu jest w stanie w każde miejsce wywołania funkcji rodzica, wstawić ciało tej funkcji. W pozostałych sytuacjach tego nie robi, więc funkcja jest niejako... pół-inline :-)
Nie istnieje jedna funkcja, którą raz się opłaca dawać inline, a raz nie.
Z punktu widzenia kompilatora, jak najbardziej istnieje. Taki f(x) może być nie inline'owaną funkcją, ale już z f(0) kompilator może więcej wywnioskować i być może wykonać inlining.
kod generowany z obsługą wywołania funkcji i powrotem zajmie więcej pamięci niż wklejenie jej ciała 1000 razy gdzieś w kodzie.
Niemożliwe, bo różnica powinna być widoczna tylko na stosie. Do tego musiała by być silnie rekurencyjna. W ogóle nie powinieneś się przejmować zużyciem stosu, póki nie dociągniesz do stack overflow.
Jeśli funkcja jest spora, to nigdy nie opłaca Ci się dawać jej inline.
Jeśli wywołujesz ją w dokładnie jednym miejscu w kodzie, to wtedy najbardziej się opłaca, niezależnie od wielkości.
Mieszasz "inline" o którego obecności decyduje user (i czasem reguły języka) oraz "inlining", który leży całkowicie w gestii kompilatora (póki nie użyje się rzeczy w style __declspec((noinline)) ). Z roku na rok te terminy stają się coraz bardziej odległe.
93,459 zapytań
142,453 odpowiedzi
322,722 komentarzy
62,837 pasjonatów
Motyw:
Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡
Oto polecana książka warta uwagi.Pełną listę książek znajdziesz tutaj