Kiedy powinienem napisać słowo kluczowe „inline” dla funkcji / metody?

562

Kiedy powinienem napisać słowo kluczowe inlinedla funkcji / metody w C ++?

Po wyświetleniu odpowiedzi na niektóre pytania:

  • Kiedy mam nie napisać słowa kluczowego „inline” dla funkcji / metody w C ++?

  • Kiedy kompilator nie będzie wiedział, kiedy ustawić funkcję / metodę jako „wbudowaną”?

  • Czy to ważne, czy aplikacja jest wielowątkowa, gdy pisze się „wbudowany” dla funkcji / metody?

Częściowy
źródło
40
Jeśli zdefiniujesz funkcję w nagłówku, musisz zadeklarować ją w linii. W przeciwnym razie pojawią się błędy linkera dotyczące wielu definicji funkcji.
Martin York,
15
@Martin: Być wybrednym, chyba że jest to definicja klasy.
David Thornley,
20
@David: Aby być wyjątkowo wybrednym, to tylko dlatego, że takie funkcje są domyślnie oznaczone inline(9.3 / 2).
Wyścigi lekkości na orbicie
Zobacz także Funkcje wbudowane w C ++ FAQ. Mają bardzo dobre leczenie inline.
jww

Odpowiedzi:

882

O rany, jeden z moich domowych rękawów.

inlinejest bardziej niż staticlub externnakazujący kompilatorowi wstawienie twoich funkcji. extern, static, inlineSą dyrektywami podnośnik, używane niemal wyłącznie przez łącznik, a nie kompilator.

Mówi się, że inlinesugeruje to kompilatorowi, że według ciebie funkcja powinna być wbudowana. Być może było to prawdą w 1998 roku, ale dekadę później kompilator nie potrzebuje takich wskazówek. Nie wspominając, że ludzie zwykle mylą się, jeśli chodzi o optymalizację kodu, więc większość kompilatorów całkowicie ignoruje „podpowiedź”.

  • static- nazwy zmiennej / funkcji nie można używać w innych jednostkach tłumaczeniowych. Linker musi się upewnić, że przypadkowo nie używa statycznie zdefiniowanej zmiennej / funkcji z innej jednostki tłumaczeniowej.

  • extern- użyj tej zmiennej / nazwy funkcji w tej jednostce tłumaczeniowej, ale nie narzekaj, jeśli nie jest zdefiniowana. Linker to uporządkuje i upewni się, że cały kod, który próbował użyć jakiegoś symbolu zewnętrznego, ma swój adres.

  • inline- ta funkcja zostanie zdefiniowana w wielu jednostkach tłumaczeniowych, nie martw się o to. Linker musi upewnić się, że wszystkie jednostki tłumaczeniowe używają pojedynczego wystąpienia zmiennej / funkcji.

Uwaga: Ogólnie rzecz biorąc, deklarowanie szablonów inlinejest bezcelowe, ponieważ mają one już semantykę łączenia inline. Jednak wyraźna specjalizacja i tworzenie szablonów wymagainline do użycia.


Konkretne odpowiedzi na twoje pytania:

  • Kiedy powinienem napisać słowo kluczowe „inline” dla funkcji / metody w C ++?

    Tylko wtedy, gdy chcesz, aby funkcja była zdefiniowana w nagłówku. Dokładniej tylko wtedy, gdy definicja funkcji może pojawiać się w wielu jednostkach tłumaczeniowych. Dobrym pomysłem jest zdefiniowanie małych (jak w jednej linijce) funkcji w pliku nagłówkowym, ponieważ daje to kompilatorowi więcej informacji do pracy przy optymalizacji kodu. Zwiększa także czas kompilacji.

  • Kiedy nie powinienem pisać słowa kluczowego „inline” dla funkcji / metody w C ++?

    Nie dodawaj inline tylko dlatego, że uważasz, że Twój kod będzie działał szybciej, jeśli kompilator go wstawi.

  • Kiedy kompilator nie będzie wiedział, kiedy ustawić funkcję / metodę jako „wbudowaną”?

    Ogólnie rzecz biorąc, kompilator będzie w stanie to zrobić lepiej niż ty. Jednak kompilator nie ma opcji wstawiania kodu, jeśli nie ma definicji funkcji. W maksymalnie zoptymalizowanym kodzie zazwyczaj wszystkie privatemetody są wprowadzane niezależnie od tego, czy o to poprosisz, czy nie.

    Na bok, aby zapobiec wstawianiu w GCC, użyj __attribute__(( noinline ))i w Visual Studio, użyj __declspec(noinline).

  • Czy to ważne, czy aplikacja jest wielowątkowa, gdy pisze się „wbudowany” dla funkcji / metody?

    Wielowątkowość nie wpływa w żaden sposób na wstawianie.

deft_code
źródło
172
+1 Najlepszy opis inline, jaki widziałem w ... (na zawsze). Teraz zdzieram cię i używam tego we wszystkich moich objaśnieniach słowa kluczowego.
Martin York,
6
@Ziggy, próbowałem powiedzieć, że wbudowane kompilatory i inlinesłowo kluczowe nie są powiązane. Masz jednak dobry pomysł. Z reguły zgadywanie, co można by poprawić poprzez wstawianie, jest bardzo podatne na błędy. Wyjątkiem od tej reguły jest jeden liniowiec.
deft_code
4
Ta odpowiedź trochę mnie myli. Mówisz wszystko o tym, że kompilator może lepiej wstawiać / nie wstawiać rzeczy. Następnie mówisz, że powinieneś umieścić jeden nagłówek / małe funkcje w nagłówku i że kompilator nie może wstawić kodu bez definicji funkcji. Czy to nie jest trochę sprzeczne? Dlaczego nie po prostu włożyć wszystkiego do pliku CPP i pozwolić kompilatorowi zdecydować?
user673679,
5
Kompilator będzie wstawiał wywołania funkcji tylko tam, gdzie definicja jest dostępna w witrynie wywoływania. Pozostawienie wszystkich funkcji w pliku cpp ograniczy wstawianie do tego pliku. Sugeruję zdefiniowanie małych linijek w pliku .h, ponieważ koszt prędkości kompilacji jest znikomy i masz prawie gwarancję, że kompilator wstawi wywołanie. Chodzi mi o wbudowanie kompilatora w to, że jest to port czarnej sztuki optymalizacji, w której twój kompilator jest znacznie lepszy od ciebie.
deft_code
8
Ilekroć czytam coś na temat kumulatywnej wiedzy w Internecie, muszę pomyśleć o słynnym cytacie Johna Lawtona: Ironią epoki informacyjnej jest to, że nadała nowy szacunek niedoinformowanym opiniom.
IInspectable
60

Chciałbym przyczynić się do wszystkich wspaniałych odpowiedzi w tym wątku przekonującym przykładem, aby rozwiać wszelkie pozostałe nieporozumienia.

Biorąc pod uwagę dwa pliki źródłowe, takie jak:

  • inline111.cpp:

    #include <iostream>
    
    void bar();
    
    inline int fun() {
      return 111;
    }
    
    int main() {
      std::cout << "inline111: fun() = " << fun() << ", &fun = " << (void*) &fun;
      bar();
    }
  • inline222.cpp:

    #include <iostream>
    
    inline int fun() {
      return 222;
    }
    
    void bar() {
      std::cout << "inline222: fun() = " << fun() << ", &fun = " << (void*) &fun;
    }

  • Przypadek A:

    Kompiluj :

    g++ -std=c++11 inline111.cpp inline222.cpp

    Wyjście :

    inline111: fun() = 111, &fun = 0x4029a0
    inline222: fun() = 111, &fun = 0x4029a0

    Dyskusja :

    1. Nawet jeśli powinieneś mieć identyczne definicje funkcji wbudowanych, kompilator C ++ nie oflaguje go, jeśli tak nie jest (w rzeczywistości z powodu osobnej kompilacji nie ma możliwości sprawdzenia). Zapewnienie tego jest Twoim obowiązkiem!

    2. Linker nie narzeka na regułę jednej definicji , jak fun()to zostało zadeklarowane jako inline. Ponieważ jednak inline111.cpp jest pierwszą jednostką translacyjną (która faktycznie wywołuje fun()) przetwarzaną przez kompilator, kompilator tworzy instancję fun()po pierwszym spotkaniu wywołania w inline111.cpp . Jeśli kompilator zdecyduje się nie rozszerzać fun()swojego wywołania z dowolnego miejsca w twoim programie ( np. Z inline222.cpp ), wywołanie do fun()zawsze będzie połączone z instancją utworzoną z inline111.cpp (wywołanie do fun()wewnątrz inline222.cppmoże również utworzyć wystąpienie w tej jednostce tłumaczeniowej, ale pozostanie niepowiązane). Rzeczywiście wynika to z identycznych &fun = 0x4029a0wydruków.

    3. Wreszcie, pomimo inlinesugestii kompilatora, aby faktycznie rozszerzyć jednowierszową fun(), całkowicie ignoruje twoją sugestię, co jest jasne, ponieważ fun() = 111w obu liniach.


  • Przypadek B:

    Kompiluj (zauważ odwrotną kolejność) :

    g++ -std=c++11 inline222.cpp inline111.cpp

    Wyjście :

    inline111: fun() = 222, &fun = 0x402980
    inline222: fun() = 222, &fun = 0x402980

    Dyskusja :

    1. Przypadek ten potwierdza co zostały omówione w sprawie A .

    2. Zwróć uwagę na ważny punkt, że jeśli skomentujesz rzeczywiste wywołanie fun()w inline222.cpp ( np. Całkowicie przestajesz komentować coutw inline222.cpp ), to, pomimo kolejności kompilacji twoich jednostek tłumaczeniowych, fun()zostanie utworzone natychmiast po pierwszym spotkaniu w inline111.cpp , czego wynikiem jest wydruk dla przypadku B as inline111: fun() = 111, &fun = 0x402980.


  • Sprawa C:

    Kompilacja (powiadomienie -O2) :

    g++ -std=c++11 -O2 inline222.cpp inline111.cpp

    lub

    g++ -std=c++11 -O2 inline111.cpp inline222.cpp

    Wyjście :

    inline111: fun() = 111, &fun = 0x402900
    inline222: fun() = 222, &fun = 0x402900

    Dyskusja :

    1. Jak opisano tutaj , -O2optymalizacja zachęca kompilator do faktycznego rozszerzenia funkcji, które można wprowadzić (zauważ również, że -fno-inlinejest to domyślna opcja bez opcji optymalizacji). Jak widać tutaj na wydruku , fun()faktycznie został on wbudowany (zgodnie z jego definicją w tej konkretnej jednostce tłumaczeniowej), co skutkuje dwoma różnymi fun() wydrukami. Mimo to wciąż istnieje tylko jedna globalnie połączona instancja fun()(zgodnie z wymogami standardu), co wynika z identycznego &fun wydruku.
Alaroff
źródło
8
Twoja odpowiedź jest ilustrującym postem, dlaczego język sprawia, że ​​takie inlinefunkcje są niezdefiniowanym zachowaniem.
R Sahu
Powinieneś również dodać przypadki, w których kompilacja i łączenie są oddzielne, przy .cppczym każda z nich jest własną jednostką tłumaczeniową. Najlepiej dodaj przypadki -fltowłączonych / wyłączonych.
syockit,
Odwołanie do C ++ wyraźnie mówi: „Jeśli funkcja wbudowana lub zmienna (od C ++ 17) z zewnętrznym powiązaniem jest różnie zdefiniowana w różnych jednostkach tłumaczeniowych, zachowanie jest niezdefiniowane.” Więc napisane przez ciebie rzeczy są specyficzne dla GCC, ponieważ są efektem ubocznym koordynacji procesów kompilacji i łączenia. Zauważ też, że może się to różnić w zależności od wersji.
Petr Fiedler
27

Nadal musisz jawnie wstawić swoją funkcję podczas specjalizacji szablonu (jeśli specjalizacja znajduje się w pliku .h)

BostonLogan
źródło
21

1) W dzisiejszych czasach prawie nigdy. Jeśli dobrym pomysłem jest wstawienie funkcji, kompilator zrobi to bez twojej pomocy.

2) Zawsze. Zobacz nr 1.

(Edytowane, aby odzwierciedlić, że podzieliłeś swoje pytanie na dwa pytania ...)

Aric TenEyck
źródło
Tak. Inline jest jedynie wskazówką dla kompilatora i można go zignorować. Obecnie kompilator prawdopodobnie wie lepiej niż programista, które funkcje najlepiej wbudować.
Mark Byers,
1
Tak, ale jest mniej istotne - aby funkcja mogła zostać wstawiona, jej treść musi znajdować się w tej samej jednostce kompilacji (na przykład w nagłówku). Jest to mniej powszechne w programach C.
Michael Kohne,
1
zdefiniowanie szablonu funkcji innej niż element (aka niestatyczny szablon funkcji) nie wymaga wstawiania. Patrz jedna reguła definicji (3.2 / 5).
deft_code
2
-1: inlinejest nadal potrzebne, na przykład do zdefiniowania funkcji w pliku nagłówkowym (i jest to wymagane do wstawienia takiej funkcji w kilku jednostkach kompilacji).
Melebius
1
@ Etienne, które jest specyficzne dla implementacji. Zgodnie ze standardem istnieje reguła jednej definicji, co oznacza, że ​​jeśli naiwnie umieścisz definicję funkcji w wielu jednostkach tłumaczeniowych, otrzymasz błąd. Ale jeśli ta funkcja ma inlinespecyfikator, jej instancje są automatycznie łączone w jedną przez linker i ODR nie jest używany.
Ruslan
12

Kiedy nie powinienem pisać słowa kluczowego „inline” dla funkcji / metody w C ++?

Jeśli funkcja jest zadeklarowana w nagłówku i zdefiniowane w .cpppliku, należy nie napisać słowa kluczowego.

Kiedy kompilator nie będzie wiedział, kiedy ustawić funkcję / metodę jako „wbudowaną”?

Nie ma takiej sytuacji. Kompilator nie może ustawić funkcji w linii. Wszystko, co może zrobić, to wstawić niektóre lub wszystkie wywołania funkcji. Nie może tego zrobić, jeśli nie ma kodu funkcji (w takim przypadku linker musi to zrobić, jeśli jest w stanie to zrobić).

Czy to ważne, czy aplikacja jest wielowątkowa, gdy pisze się „wbudowany” dla funkcji / metody?

Nie, to wcale nie ma znaczenia.

Johannes Schaub - litb
źródło
Istnieją przypadki, w których właściwe jest użycie wbudowanego pliku .cpp. Np. Zastosowanie optymalizacji do kodu całkowicie zależnego od implementacji.
Robin Davies,
@RobinDavies zaktualizowana odpowiedź. Wygląda na to, że źle zrozumiałeś, co chciałem napisać.
Johannes Schaub - litb
5
  • Kiedy kompilator nie będzie wiedział, kiedy ustawić funkcję / metodę jako „wbudowaną”?

Zależy to od zastosowanego kompilatora. Nie ślepo ufaj, że w dzisiejszych czasach kompilatory wiedzą lepiej niż ludzie, jak wstawiać i nigdy nie powinieneś używać go ze względu na wydajność, ponieważ jest to dyrektywa dotycząca łączenia, a nie wskazówka optymalizacyjna. Chociaż zgadzam się, że ideologicznie te argumenty są prawidłowe, spotkanie z rzeczywistością może być czymś innym.

Po przeczytaniu wielu wątków z ciekawości wypróbowałem efekty inline na kodzie, po prostu pracuję, a wyniki były takie, że uzyskałem mierzalne przyspieszenie dla GCC i brak przyspieszenia dla kompilatora Intela.

(Więcej szczegółów: symulacje matematyczne z kilkoma funkcjami krytycznymi zdefiniowanymi poza klasą, GCC 4.6.3 (g ++ -O3), ICC 13.1.0 (icpc -O3); dodanie inline do punktów krytycznych spowodowało + 6% przyspieszenia z kodem GCC).

Jeśli więc zakwalifikujesz GCC 4.6 jako nowoczesny kompilator, wynik będzie taki, że dyrektywa wbudowana nadal ma znaczenie, jeśli piszesz zadania wymagające dużej mocy obliczeniowej procesora i wiesz, gdzie dokładnie jest wąskie gardło.

meda beda
źródło
6
Chciałbym zobaczyć więcej dowodów na poparcie swoich roszczeń. Podaj kod, który testujesz, a także dane wyjściowe asemblera z wbudowanym słowem kluczowym i bez niego. Dowolna liczba rzeczy mogłaby dać ci korzyści w zakresie wydajności.
void.pointer
1
Wreszcie ktoś, kto nie tylko powtórzy to, co mówią inni, ale faktycznie zweryfikuje te stwierdzenia. Gcc rzeczywiście nadal uważa słowo kluczowe inline za wskazówkę (myślę, że clang ignoruje je całkowicie).
MikeMB
@ void.pointer: Dlaczego tak trudno w to uwierzyć? Gdyby optymalizatory były już idealne, nowe wersje nie mogłyby poprawić wydajności programu. Ale regularnie to robią.
MikeMB,
3

W rzeczywistości prawie nigdy. Wszystko, co robisz, to sugerowanie, aby kompilator wstawił daną funkcję do siebie (np. Zastąp wszystkie wywołania tej funkcji / w jej treści). Oczywiście nie ma gwarancji: kompilator może zignorować dyrektywę.

Kompilator ogólnie dobrze sobie radzi z wykrywaniem i optymalizowaniem takich rzeczy.

DarkSquid
źródło
7
Problem polega na tym, że inlinema semantyczną różnicę w C ++ (np. W sposobie traktowania wielu definicji), co jest ważne w niektórych przypadkach (np. Szablony).
Pavel Minaev,
4
inline służy do rozwiązywania przypadków, w których symbol ma wiele definicji. Jednak szablony są już obsługiwane przez język. Jednym wyjątkiem jest wyspecjalizowana funkcja szablonu, która nie ma już żadnych parametrów szablonu (szablon <>). Są one traktowane bardziej jak funkcje niż szablony, dlatego do połączenia potrzebne jest słowo kluczowe inline.
deft_code,
2

gcc domyślnie nie wstawia żadnych funkcji podczas kompilacji bez włączonej optymalizacji. Nie wiem o studiu wizualnym - deft_code

Sprawdziłem to w Visual Studio 9 (15.00.30729.01), kompilując z / FAcs i patrząc na kod asemblera: Kompilator wygenerował wywołania funkcji członka bez włączonej optymalizacji w trybie debugowania . Nawet jeśli funkcja jest oznaczona __forceinline , nie jest generowany wbudowany kod środowiska wykonawczego.

Jedzia
źródło
1
Włącz / Ścianę, aby dowiedzieć się, które funkcje zostały oznaczone jako wstawiane, ale nie zostały wstawione
Paul
0

Chcesz umieścić go na samym początku, przed typem zwrotu. Ale większość kompilatorów to ignoruje. Jeśli jest zdefiniowany i ma mniejszy blok kodu, większość kompilatorów i tak uważa go za wbudowany.

Jeremy Morgan
źródło
0

O ile nie piszesz biblioteki lub nie masz specjalnych powodów, możesz zapomnieć o optymalizacji łączainline i użyć jej zamiast tego. Usuwa wymóg, że definicja funkcji musi znajdować się w nagłówku, aby można ją było uwzględnić podczas wstawiania między jednostkami kompilacji, co dokładnie pozwala.inline

(Ale patrz: Czy jest jakiś powód, dla którego nie należy korzystać z optymalizacji czasu łącza? )

n.caillou
źródło
0

Inline słowo kluczowe żąda od kompilatora zamiany wywołania funkcji na treść funkcji, najpierw ocenia wyrażenie, a następnie przekazuje. Zmniejsza to narzut wywołania funkcji, ponieważ nie ma potrzeby przechowywania adresu zwrotnego, a pamięć funkcji nie jest wymagana dla funkcji argumenty.

Kiedy użyć:

  • Aby poprawić wydajność
  • Aby zmniejszyć obciążenie połączeń.
  • Ponieważ jest to tylko prośba do kompilatora, niektóre funkcje nie będą wstawiane * duże funkcje
    • funkcje posiadające zbyt wiele argumentów warunkowych
    • kod rekurencyjny i kod z pętlami itp.
Blacha
źródło
Warto wiedzieć, że tak nie jest. Poziom optymalizacji od -O0 do -Ofast określa, czy funkcja jest wbudowana, czy nie. Inline przy regularnej kompilacji (-O0) nie wstawi funkcji niezależnie od tego, czy używasz inlineC czy C ++. C Inline: stackoverflow.com/a/62287072/7194773 C ++ inline: stackoverflow.com/a/62230963/7194773
Lewis Kelsey
0

C ++ Inline jest zupełnie inny niż C inline .

#include <iostream>
extern inline int i[];
int i [5];
struct c {
  int function (){return 1;} //implicitly inline
  static inline int j = 3; //explicitly inline
};
int main() {
  c j;
  std::cout << i;
}

inlinesam wpływa na kompilator, asembler i linker. Jest to dyrektywa dla kompilatora, która mówi, że emituje tylko symbol tej funkcji / danych, jeśli jest on używany w jednostce tłumaczącej, a jeśli tak, to podobnie jak metody klasowe, każ asemblerowi, aby zapisał je w sekcji .section .text.c::function(),"axG",@progbits,c::function(),comdatlub .section .bss.i,"awG",@nobits,i,comdatdanych.

To następuje .section name, "flags"MG, @type, entsize, GroupName[, linkage]. Na przykład nazwa sekcji jest i nie jest używana, jest teraz widoczna dla asemblera, aw rezultacie linkera, ponieważ nie jest przechowywany w regularnym.text.c::function() . axGoznacza, że ​​sekcja jest alokowalna, wykonywalna i w grupie, tj. zostanie podana nazwa grupy (i nie ma flagi M, więc nie zostanie podany żaden rozmiar); lub etc przez montera z powodu ich dyrektyw.@progbitsoznacza, że ​​sekcja zawiera dane i nie jest pusta; c::function()to nazwa grupy i grupa macomdatpowiązanie oznacza, że ​​we wszystkich plikach obiektowych wszystkie sekcje napotkane z tą nazwą grupy oznaczone tagiem comdat zostaną usunięte z ostatecznego pliku wykonywalnego, z wyjątkiem 1, tzn. kompilator upewnia się, że w jednostce tłumaczącej jest tylko jedna definicja, a następnie mówi asemblerowi, aby wstawił we własnej grupie w pliku obiektowym (1 sekcja w 1 grupie), a następnie linker upewni się, że jeśli jakiś plik obiektowy ma grupę o tej samej nazwie, to umieści tylko jeden w końcowym .exe. Różnica pomiędzyinlineinline.data.text

static inlinew klasie oznacza, że ​​jest to definicja typu, a nie deklaracja (pozwala zdefiniować element statyczny w klasie) i uczynić ją wbudowaną; teraz działa jak wyżej.

static inlinew zakresie plików wpływa tylko na kompilator. Oznacza to, że dla kompilatora: emituje symbol tej funkcji / danych tylko wtedy, gdy jest używany w jednostce tłumaczącej i robi to jako zwykły symbol statyczny (przechowuj tekst. / Tekst bez dyrektywy .globl). Dla asemblera nie ma teraz różnicy między staticistatic inline

extern inlineto deklaracja, która oznacza, że ​​musisz zdefiniować ten symbol w jednostce tłumaczeniowej lub wyrzucić błąd kompilatora; jeśli jest zdefiniowany, traktuj go jako zwykły, inlinea dla asemblera i linkera nie będzie różnicy między extern inlinei inline, więc jest to tylko ochrona kompilatora.

extern inline int i[];
extern int i[]; //allowed repetition of declaration with incomplete type, inherits inline property
extern int i[5]; //declaration now has complete type
extern int i[5]; //allowed redeclaration if it is the same complete type or has not yet been completed
extern int i[6]; //error, redeclaration with different complete type
int i[5]; //definition, must have complete type and same complete type as the declaration if there is a declaration with a complete type

Wszystko powyższe bez wiersza błędu zwija się do inline int i[5]. Oczywiście, jeśli tak, extern inline int i[] = {5};to externzostaniesz zignorowany z powodu wyraźnej definicji poprzez przypisanie.

inlinew przestrzeni nazw zobacz to i to

Lewis Kelsey
źródło
-1

Podczas opracowywania i debugowania kodu pomiń inline. Komplikuje to debugowanie.

Głównym powodem ich dodania jest pomoc w optymalizacji wygenerowanego kodu. Zazwyczaj zamienia to zwiększoną przestrzeń kodu na szybkość, ale czasami inlineoszczędza zarówno przestrzeń kodu, jak i czas wykonania.

Przedyskutowanie tego rodzaju myśli na temat optymalizacji wydajności przed zakończeniem algorytmu jest przedwczesną optymalizacją .

wallyk
źródło
12
inlinefunkcje zwykle nie są wstawiane, chyba że są kompilowane z optymalizacjami, więc nie wpływają w żaden sposób na debugowanie. Pamiętaj, że to wskazówka, a nie żądanie.
Pavel Minaev,
3
gcc domyślnie nie wstawia żadnych funkcji podczas kompilacji bez włączonej optymalizacji. Nie wiem o studiu wizualnym
deft_code,
Pracowałem nad ogromnym projektem g ++, w którym włączono debugowanie. Być może inne opcje temu zapobiegały, ale inlinefunkcje były wbudowane. Niemożliwe było ustalenie w nich znaczącego punktu przerwania.
wallyk
2
włączenie debugowania nie przestaje być wbudowane w gcc. Jeśli jakakolwiek optymalizacja jest włączona (-O1 lub wyższa), gcc spróbuje wstawić najbardziej oczywiste przypadki. Tradycyjnie GDB miał trudności z punktami przerwania i konstruktorami, szczególnie wbudowanymi konstruktorami. Zostało to jednak naprawione w najnowszych wersjach (przynajmniej 6.7, może wcześniej).
deft_code
2
Dodanie inlinenic nie poprawi kodu w nowoczesnym kompilatorze, który może dowiedzieć się, czy wstawić, czy nie.
David Thornley,
-1

Kiedy należy wstawić:

1.Jeśli chcemy uniknąć narzutu rzeczy, które wywoływane są podczas wywoływania funkcji, takich jak przekazywanie parametrów, przekazywanie kontroli, powrót kontroli itp.

2. Funkcja powinna być niewielka, często wywoływana, a wstawianie jest naprawdę korzystne, ponieważ zgodnie z zasadą 80-20, spróbuj ustawić te funkcje, które mają duży wpływ na wydajność programu.

Ponieważ wiemy, że inline to tylko prośba do kompilatora podobna do rejestracji i będzie kosztować cię w rozmiarze kodu obiektu.

Ashish
źródło
„Inline to tylko żądanie kompilatora podobne do rejestracji” Są podobne, ponieważ ani nie są żądaniami, ani nie mają nic wspólnego z optymalizacją. inlineutraciło status wskazówki optymalizacyjnej, a większość kompilatorów używa go tylko do uwzględnienia wielu definicji - tak jak powinny IMO. Co więcej, od czasu C ++ 11 registerjest całkowicie przestarzałe ze względu na wcześniejsze znaczenie „Wiem lepiej niż kompilator, jak zoptymalizować”: teraz jest to tylko słowo zastrzeżone, bez aktualnego znaczenia.
underscore_d
@underscore_d: Gcc nadal inlinedo pewnego stopnia słucha .
MikeMB,
-1

Funkcja wbudowana w C ++ to potężna koncepcja, która jest powszechnie stosowana w klasach. Jeśli funkcja jest wbudowana, kompilator umieszcza kopię kodu tej funkcji w każdym punkcie, w którym funkcja jest wywoływana w czasie kompilacji.

Każda zmiana funkcji wbudowanej może wymagać ponownej kompilacji wszystkich klientów funkcji, ponieważ kompilator musiałby ponownie zastąpić cały kod, w przeciwnym razie kontynuowałby ze starą funkcjonalnością.

Aby wstawić funkcję, umieść słowo kluczowe inline przed nazwą funkcji i zdefiniuj funkcję przed wykonaniem jakichkolwiek wywołań funkcji. Kompilator może zignorować kwalifikator wbudowany, jeśli zdefiniowana funkcja jest większa niż linia.

Definicja funkcji w definicji klasy jest definicją funkcji wbudowanej, nawet bez użycia specyfikatora wbudowanego.

Poniżej znajduje się przykład, który wykorzystuje funkcję wstawiania do zwrócenia maksymalnie dwóch liczb

#include <iostream>

using namespace std;

inline int Max(int x, int y) { return (x > y)? x : y; }

// Main function for the program
int main() {
   cout << "Max (100,1010): " << Max(100,1010) << endl;

   return 0;
}

Aby uzyskać więcej informacji, zobacz tutaj .

amirfg
źródło