Question Comment fonctionnent les variables en ligne?


Lors de la réunion des normes ISO C ++ d’Oulu en 2016, une proposition intitulée Variables en ligne a été voté en C ++ 17 par le comité de normalisation.

En termes simples, quelles 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?


69
2018-06-26 21:39


origine


Réponses:


La première phrase de la proposition:

" Leinline spécificateur peut être appliqué aux variables aussi bien qu'aux fonctions.

L'effet garanti de inline 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. En pratique, cela signifie que vous devez définir la fonction dans un en-tête, ce qui peut être inclus dans plusieurs unités de traduction. La proposition étend cette possibilité aux variables.

Ainsi, dans la pratique, la proposition (désormais acceptée) vous permet d’utiliser la inline mot-clé pour définir un lien externe const variable de portée d'espace de noms, ou tout static membre de données de classe, dans un fichier d'en-tête, de sorte que les multiples définitions qui en résultent lorsque cet en-tête est inclus dans plusieurs unités de traduction sont correctes avec l'éditeur de liens - il choisit simplement un d'eux.

Jusqu'à et y compris C ++ 14, la machine interne pour cela a été là, afin de soutenir static variables dans les modèles de classe, mais il n'y avait pas de moyen pratique d'utiliser cette machine. Il fallait avoir recours à des astuces comme

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`.

A partir de C ++ 17 et suivants, je crois qu'on peut écrire juste

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

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

... dans un fichier d'en-tête.

La proposition comprend le libellé

" Un membre de données statique en ligne peut être défini dans la définition de classe et peut spécifier un initialiseur d'accolade ou d'égalité. Si le membre est déclaré avec le constexpr spécificateur, il peut être redéclaré dans la portée de l'espace de nommage sans initialiseur (cet usage est obsolète, voir D.X). Les déclarations d'autres membres de données statiques ne doivent pas spécifier un itializer d'accolade ou d'égalité

... ce qui permet de simplifier davantage ce qui précède

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

... comme noté par T.C dans un commentaire à cette réponse.

Également​constexprSpécificateur implique inlinepour les membres de données statiques ainsi que les fonctions.


Remarques:
¹ Pour une fonction inline a également un effet incitatif 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. Cet indice peut être ignoré.


75
2018-06-26 21:55



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 autre copie n'est créée.

Les variables en ligne peuvent être utilisées pour définir des globales dans les bibliothèques en-tête uniquement. Avant C ++ 17, ils devaient utiliser des solutions de contournement (fonctions en ligne ou hacks de modèle).

Par exemple, une solution consiste à utiliser le singleton de Meyer avec une fonction inline:

inline T& instance()
{
  static T global;
  return global;
}

Cette approche présente certains inconvénients, principalement en termes de performance. Cette solution pourrait être évitée par des solutions de modèle, mais il est facile de les tromper.

Avec les variables en ligne, vous pouvez directement le déclarer (sans obtenir d'erreur de l'éditeur de liens à plusieurs définitions):

inline T global;

En dehors des bibliothèques en-tête seulement, il existe d'autres cas où les variables en ligne peuvent aider. Nir Friedman aborde ce sujet dans son discours à CppCon: Ce que les développeurs C ++ doivent savoir sur les globals (et l'éditeur de liens). La partie sur les variables en ligne et les solutions de contournement commence à 18m9s.

En bref, si vous devez déclarer des variables globales partagées entre des unités de compilation, les déclarer en tant que variables en ligne dans le fichier d'en-tête est simple et évite les problèmes liés aux solutions de contournement antérieures à C ++ 17.

(Il y a toujours des cas d'utilisation pour le singleton de Meyer, par exemple, si vous voulez explicitement avoir une initialisation paresseuse.)


4
2017-11-27 01:14