2013-04-07 17 views

Odpowiedz

12

Możesz przestać używać inline jako techniki optymalizacji.

inline jest zasadniczo przydatna tylko wtedy, gdy chcesz, aby ODR (One Definition Rule) nie stosować. W skrócie, można oznaczyć funkcje inline i zapewnić ich definicję bezpośrednio w jednym pliku nagłówka, który następnie importowany przez wiele jednostek tłumaczeniowych, bez łącznika narzeka na ten temat:

foo.hpp

inline int foo() { return 42; } 

foo.cpp

#include "foo.hpp" // <== THE LINKER WOULD COMPLAIN IF foo() WERE NOT inline, 
        //  because its definition is imported also in main.cpp 
void bar() 
{ 
    int x = foo(); 
} 

main.cpp

#include "foo.hpp" // <== THE LINKER WOULD COMPLAIN IF foo() WERE NOT inline, 
        //  because its definition is imported also in foo.cpp 
int main() 
{ 
    std::cout << foo(); 
} 

Obecność inline kluczowego (które również nie ma gwarancji, że kompilator wykona inline) zapewnia, że ​​łącznik połączy tych definicji.

oczywiście w kolejności dla tej operacji scalania, aby mieć znaczenie, wszystko definicje funkcji oznaczone jako inline który w końcu jest udział kilku różnych jednostek tłumaczeniowych muszą być identyczne. Jeśli tak nie jest, Twój program ma Niezdefiniowane zachowanie i nie wymaga diagnostyki - co oznacza, że ​​Twój kompilator/linker nie musi wykryć tej niezgodności i powiedzieć, że coś jest nie tak!

zgodnie z pkt 3.2/4 C++ 11 standardu, w rzeczywistości:

Każdy program zawiera dokładnie jedną definicję każdej non-inline funkcji lub zmiennej, która jest odr wykorzystywane że program; diagnostyka nie jest wymagana. Definicja może pojawiać się jawnie w programie, można ją znaleźć w bibliotece standardowej lub zdefiniowanej przez użytkownika, lub (w razie potrzeby) jest ona niejawnie zdefiniowana (patrz 12.1, 12.4 i 12.8). Funkcję inline należy zdefiniować w każdej jednostce tłumaczeniowej, w której jest używana odr.

Zauważ, że można mieć taką samą funkcję oznaczoną jako inline i dosłownie zdefiniowane dwukrotnie w różnych jednostkach translacji, i to jest w porządku tak długo, jak te definicje są identyczne:

foo.cpp

inline int foo() // Has the same body in main.cpp, no problem! 
{ 
    return 42; 
} 

główny.CPP

inline int foo() // Has the same body in foo.cpp, no problem! 
{ 
    return 42; 
} 

int main() 
{ 
    std::cout << foo(); 
} 

Jednak jeśli dwie definicje różnią się, będzie wstrzyknąć UB w kodzie, jak w poniższym przykładzie:

foo.cpp

inline int foo() 
{ 
    return 42; // <== WATCH OUT! Different body in main.cpp 
} 

głównym. cpp

inline int foo() 
{ 
    return -42; // <== WATCH OUT! Different body in foo.cpp 
} 

int main() 
{ 
    std::cout << foo(); 
} 

Dlatego zwykle oznacza się funkcje jako inline, gdy podaje się ich definicję bezpośrednio w pliku nagłówkowym d. #include.

Należy również zauważyć, że funkcje członków klasy, których definicja jest bezpośrednio podkreślona w definicjach klas, są automatycznie oznaczane jako inline.

+0

Nawet jeśli nigdy nie użyjesz 'inline', możesz nadal używać go niejawnie:' struct Foo {int x; Foo(): x (0) {}}; 'w jednym pliku .cpp i' struct Foo {double d; Foo(): d (0) {}}; 'w innym pliku .cpp, a Ty właśnie utworzyłeś dwa konstruktory' inline' o nazwie 'Foo :: Foo' ... – Yakk

+1

@Yakk: Twój program ma niezdefiniowane zachowanie, chyba że oba "Foo" są zadeklarowane w anonimowym obszarze nazw. –

+0

@ MatthieuM. Tak, i widziałem, że stało się to w kodzie produkcyjnym. Zasadniczo mówię, że nawet jeśli nie użyjesz 'inline', możesz zostać przez niego ugryziony, więc musisz zrozumieć, czym jest' inline', nawet jeśli go nie używasz. – Yakk

5

Zależy od celu użycia inline.

wspólne (MIS), pojęcie:
inline jest po prostu sugestia którym kompilator może być lub może nie postępowały. Dobry kompilator i tak zrobi to, co trzeba.

Chociaż prawdą:

inline wskazuje zwykle do wykonania, że ​​rolki podstawienie funkcji organizmu w miejscu połączenia ma być korzystne zwykłe mechanizmu wywołania funkcji. Implementacja nie jest wymagana do wykonania tego śródliniowego zastąpienia w punkcie połączenia; jednakże, , nawet jeśli pominięto to podstawienie inline, przestrzegane są inne reguły (zwłaszcza w.r.t One Definition Rule) dla inline.

więc jeśli celem jest wykorzystanie optymalizacje odpowiedź brzmi:

Tak, można zaprzestać używania inline. Większość współczesnych kompilatorów zrobi to dla ciebie całkiem przyjemnie.

Ale jeśli celem wykorzystania inline jest pozwalają ominąć reguły jednej definicji i określenia ciało funkcji w pliku nagłówkowym bez zerwania ODR następnie odpowiedzieć brzmi:

NO , Aby móc ominąć ODR, musisz wyraźnie oznaczyć funkcje jako inline.

Uwaga: Funkcje użytkownika zdefiniowane w ciele klasy są niejawnie inline, ale sama nie ma zastosowania do wolnych funkcji.

Powiązane problemy