Lors de la réunion Oulu ISO C ++ Standards 2016, une proposition appelée Variables en ligne a été votée en C ++ 17 par le comité des normes.
En termes simples, que sont les variables en ligne, comment fonctionnent-elles et à quoi servent-elles? Comment les variables en ligne doivent-elles être déclarées, définies et utilisées?
const
.inline
mot-clé fait pour les fonctions. Leinline
mot-clé, lorsqu'il est appliqué aux fonctions, a un autre effet crucial, qui se traduit directement en variables. Uneinline
fonction, qui est vraisemblablement déclarée dans un fichier d'en-tête, n'entraînera pas d'erreurs de «symbole en double» au moment de la liaison, même si l'en-tête obtient#include
d par plusieurs unités de traduction. Leinline
mot-clé, lorsqu'il est appliqué aux variables, aura le même résultat exact. La fin.inline
ne s'agit que d'une requête faible et non contraignante adressée à l'optimiseur. Les compilateurs sont libres de ne pas intégrer les fonctions demandées et / ou d'intégrer celles que vous n'avez pas annotées. Le but réel duinline
mot-clé est plutôt d'éviter de multiples erreurs de définition.Réponses:
La première phrase de la proposition:
L'effet garanti de
inline
tel qu'appliqué à une fonction, est de permettre à la fonction d'être définie de manière identique, avec un lien externe, dans plusieurs unités de traduction. Pour la pratique, cela signifie définir la fonction dans un en-tête, qui peut être inclus dans plusieurs unités de traduction. La proposition étend cette possibilité aux variables.Ainsi, en termes pratiques, la proposition (maintenant acceptée) vous permet d'utiliser le
inline
mot - clé pour définir uneconst
variable d'étendue d'espace de noms de lien externe , ou toutstatic
membre de données de classe, dans un fichier d'en-tête, de sorte que les multiples définitions qui résultent lorsque cet en-tête est inclus dans plusieurs unités de traduction sont OK avec l'éditeur de liens - il en choisit simplement une .Jusqu'au C ++ 14 inclusivement, la machinerie interne pour cela était là, afin de prendre en charge les
static
variables dans les modèles de classe, mais il n'y avait aucun moyen pratique d'utiliser cette machinerie. Il fallait recourir à des trucs commeÀ partir de C ++ 17 et au-delà, je pense que l'on peut simplement écrire
… Dans un fichier d'en-tête.
La proposition comprend le libellé
… Ce qui permet de simplifier davantage ce qui précède en
… Comme l'a noté TC dans un commentaire à cette réponse.
En outre, le
constexpr
spécificateur impliqueinline
pour les membres de données statiques ainsi que pour les fonctions.Notes:
¹ Pour une fonction a
inline
également un effet d'indication sur l'optimisation, que le compilateur devrait préférer remplacer les appels de cette fonction par une substitution directe du code machine de la fonction. Cette allusion peut être ignorée.la source
Kath::hi
) n'ont pas besoin d'être const.const
restriction est entièrement supprimée.static std::string const hi = "Zzzzz...";
?Les variables en ligne sont très similaires aux fonctions en ligne. Il signale à l'éditeur de liens qu'une seule instance de la variable doit exister, même si la variable est vue dans plusieurs unités de compilation. L'éditeur de liens doit s'assurer qu'aucune copie supplémentaire n'est créée.
Les variables en ligne peuvent être utilisées pour définir des globaux dans les bibliothèques d'en-tête uniquement. Avant C ++ 17, ils devaient utiliser des solutions de contournement (fonctions en ligne ou hacks de modèles).
Par exemple, une solution de contournement consiste à utiliser le singleton de Meyer avec une fonction en ligne:
Cette approche présente quelques inconvénients, principalement en termes de performances. Cette surcharge pourrait être évitée par des solutions modèles, mais il est facile de se tromper.
Avec les variables en ligne, vous pouvez le déclarer directement (sans obtenir une erreur de l'éditeur de liens à définitions multiples):
En dehors des bibliothèques d'en-tête uniquement, il existe d'autres cas où les variables en ligne peuvent aider. Nir Friedman couvre ce sujet dans son discours à CppCon: Ce que les développeurs C ++ devraient savoir sur les globals (et le linker) . La partie sur les variables en ligne et les solutions de contournement commence à 18m9s .
Pour faire court, si vous avez besoin de déclarer des variables globales qui sont partagées entre des unités de compilation, les déclarer comme variables en ligne dans le fichier d'en-tête est simple et évite les problèmes avec les solutions de contournement pré-C ++ 17.
(Il existe encore des cas d'utilisation pour le singleton de Meyer, par exemple, si vous souhaitez explicitement avoir une initialisation paresseuse.)
la source
Exemple exécutable minimal
Cette superbe fonctionnalité C ++ 17 nous permet de:
constexpr
: Comment déclarer constexpr extern?main.cpp
notmain.hpp
notmain.cpp
Compilez et exécutez:
GitHub en amont .
Voir aussi: Comment fonctionnent les variables en ligne?
Norme C ++ sur les variables en ligne
Le standard C ++ garantit que les adresses seront les mêmes. C ++ 17 N4659 standard draft 10.1.6 "Le spécificateur en ligne":
cppreference https://en.cppreference.com/w/cpp/language/inline explique que si ce
static
n'est pas donné, alors il a un lien externe.Implémentation de variables en ligne GCC
On peut observer comment il est implémenté avec:
qui contient:
et
man nm
dit à propos deu
:nous voyons donc qu'il existe une extension ELF dédiée à cela.
Pré-C ++ 17:
extern const
Avant C ++ 17 et en C, nous pouvons obtenir un effet très similaire avec un
extern const
, ce qui conduira à l'utilisation d'un seul emplacement mémoire.Les inconvénients
inline
sont:constexpr
avec cette technique,inline
permet seulement que: Comment déclarer constexpr extern?main.cpp
notmain.cpp
notmain.hpp
GitHub en amont .
Alternatives d'en-tête pré-C ++ 17 uniquement
Ce ne sont pas aussi bons que la
extern
solution, mais ils fonctionnent et n'occupent qu'un seul emplacement mémoire:Une
constexpr
fonction, carconstexpr
impliqueinline
etinline
permet (force) la définition d'apparaître sur chaque unité de traduction :et je parie que tout compilateur décent intégrera l'appel.
Vous pouvez également utiliser une variable entière statique
const
ouconstexpr
comme dans:mais vous ne pouvez pas faire des choses comme prendre son adresse, ou bien elle devient utilisée odr, voir aussi: https://en.cppreference.com/w/cpp/language/static "Membres statiques constants" et Définition des données statiques constexpr membres
C
En C, la situation est la même que C ++ avant C ++ 17, j'ai téléchargé un exemple sur: Que signifie «statique» en C?
La seule différence est qu'en C ++, cela
const
impliquestatic
pour les globaux, mais ce n'est pas le cas en C: C ++ sémantique de `static const` vs` const`Un moyen de l'intégrer entièrement?
TODO: existe-t-il un moyen d'intégrer complètement la variable, sans utiliser de mémoire du tout?
Tout comme ce que fait le préprocesseur.
Cela nécessiterait en quelque sorte:
En relation:
Testé dans Ubuntu 18.10, GCC 8.2.0.
la source
inline
n'a presque rien à voir avec l'inlining, ni pour les fonctions ni pour les variables, malgré le mot lui-même.inline
ne dit pas au compilateur d'insérer quoi que ce soit. Il dit à l'éditeur de liens de s'assurer qu'il n'y a qu'une seule définition, ce qui était traditionnellement le travail du programmeur. Alors, "Un moyen de l'intégrer complètement?" est au moins une question totalement indépendante.