Jak działają zmienne inline?

W 2016 roku Oulu ISO C++ Standards meeting, wniosek o nazwie Inline Variables został przegłosowany do C++17 przez Komitet Normalizacyjny.

W kategoriach laika, co to są zmienne inline, jak działają i do czego są przydatne? W jaki sposób należy deklarować, definiować i używać zmiennych wbudowanych?

 76
Author: jotik, 2016-06-27

2 answers

Pierwsze zdanie wniosku:

" specyfikator inline może być stosowany zarówno do zmiennych, jak i do funkcji.

Efekt 1 guaranteed inline zastosowany do funkcji polega na tym, że funkcja może być zdefiniowana identycznie, z powiązaniem zewnętrznym, w wielu jednostkach translacyjnych. W praktyce oznacza to zdefiniowanie funkcji w nagłówku, która może być zawarta w wielu jednostkach translacyjnych. Wniosek rozszerza tę możliwość na zmienne.

Tak więc, w praktyce (obecnie akceptowana) propozycja pozwala na użycie słowa kluczowego inline do zdefiniowania zewnętrznej zmiennej przestrzeni nazw const lub dowolnego elementu danych klasy static w pliku nagłówkowym, tak aby wiele definicji, które wynikają, gdy nagłówek jest zawarty w wielu jednostkach tłumaczenia, było w porządku z linkerem – po prostu wybiera jedną z nich.

Aż do C++14 włącznie była tam wewnętrzna maszyna do tego, aby obsługa zmiennych static w szablonach klas, ale nie było wygodnego sposobu użycia tej maszyny. Trzeba było uciekać się do takich sztuczek jak

template< class Dummy >
struct Kath_
{
    static std::string const hi;
};

template< class Dummy >
std::string const Kath_<Dummy>::hi = "Zzzzz...";

using Kath = Kath_<void>;    // Allows you to write `Kath::hi`.

Od C++17 i dalej wierzę, że można pisać tylko

struct Kath
{
    static std::string const hi;
};

inline std::string const Kath::hi = "Zzzzz...";    // Simpler!

... w pliku nagłówkowym.

Wniosek zawiera sformułowanie

" inline statyczny element danych może być zdefiniowany w definicji klasy i może określać nawias-lub-equal-initializer. Jeśli członek jest zadeklarowany za pomocą constexpr specifier, może być ponownie zadeklarowany w przestrzeni nazw bez inicjalizacji (użycie to jest przestarzałe; patrz D. X). Deklaracje innych członków danych statycznych nie określają nawiasu-lub-equal-inicjalizatora

... co pozwala na dalsze uproszczenie powyższego Do tylko

struct Kath
{
    static inline std::string const hi = "Zzzzz...";    // Simplest!
};

... Jak zauważył T. C w komentarz do tej odpowiedzi.

Ponadto, specyfikator ​constexpr implikuje inline dla statycznych elementów danych jak również funkcje.


Uwagi:
1 dla funkcji inline ma również wpływ na optymalizację, że kompilator powinien preferować zastąpienie wywołań tej funkcji bezpośrednią substytucją kodu maszynowego funkcji. Tę podpowiedź można zignorować.

 78
Author: Cheers and hth. - Alf,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 10:31:32

Zmienne Inline są bardzo podobne do funkcji inline. Sygnalizuje linkerowi, że powinna istnieć tylko jedna instancja zmiennej, nawet jeśli zmienna jest widoczna w wielu jednostkach kompilacji. Łącznik musi upewnić się, że nie są tworzone kolejne kopie.

Zmienne Inline mogą być używane do definiowania globali tylko w bibliotekach nagłówkowych. Przed C++17 musieli używać obejść (funkcji wbudowanych lub szablonów).

Na przykład, jednym z obejścia jest użycie singletonu Meyera z funkcja inline:

inline T& instance()
{
  static T global;
  return global;
}
Istnieją pewne wady tego podejścia, głównie pod względem wydajności. Tego narzutu można uniknąć dzięki rozwiązaniom szablonów, ale łatwo je pomylić.

Ze zmiennymi inline, można ją bezpośrednio zadeklarować (bez błędu linkera wielokrotnej definicji):

inline T global;

Oprócz bibliotek nagłówkowych, istnieją inne przypadki, w których zmienne inline mogą pomóc. Nir Friedman omawia ten temat w swoim wykładzie na CppCon: What C++ programiści powinni wiedzieć o globals (i linkerze) . Część o zmiennych inline i obejściach zaczyna się od 18m9s.

W skrócie, jeśli chcesz zadeklarować globalne zmienne, które są współdzielone między jednostkami kompilacji, zadeklarowanie ich jako zmiennych inline w pliku nagłówkowym jest proste i pozwala uniknąć problemów z obejściami w języku pre-C++17.

(są jeszcze przypadki użycia singletonu Meyera, na przykład, jeśli chcesz mieć leniwe inicjalizacja.)

 5
Author: Philipp Claßen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-11-27 01:21:54