6
votes

Les fonctions sont-elles définies dans les en-têtes garanties pour être inlinées?

Si je définis une fonction non membre dans une en-tête, elle sera toujours inlinée par le compilateur ou le compilateur choisit-il en fonction de ses heuristiques? Je sais que __inline n'est qu'un indice, c'est la même chose avec des fonctions dans les en-têtes?


0 commentaires

5 Réponses :


2
votes

Il choisira en fonction des heuristiques. Assurez-vous de le déclarer comme inline explicitement, sinon vous pouvez obtenir une erreur de liaison de symbole dupliquée si vous incluez l'en-tête dans plusieurs unités de compilation.


0 commentaires

11
votes

N'oubliez pas que ce que quelque chose d'un en-tête n'est pas différent de celui de la saisir directement dans le fichier source. Donc, être dans un en-tête ne fait aucune différence aussi loin que le compilateur; il n'a jamais su que c'était là.

Ainsi, lorsque vous définissez une fonction dans un fichier d'en-tête et que vous incluez ce fichier d'en-tête dans un fichier, c'est comme si vous avez simplement tapé la fonction directement dans le fichier. Alors maintenant, la question est: «Le compilateur choisit-il de faire des choses en ligne en fonction de la heuristique?»

La réponse est "Cela dépend du compilateur". La norme ne garantit aucune garantie sur ce qui est inlincé ou non. Cela dit, tout compilateur moderne sera extrêmement intelligent sur ce qu'il inline, probablement avec des heuristiques.

Cependant, nous arrivons à un point intéressant. Imaginez que vous ayez une fonction dans un en-tête et vous incluez cet en-tête dans plusieurs fichiers source. Vous aurez alors plusieurs définitions de la fonction, entre les unités de traduction, ce qui enfreint la règle d'une définition. Ergo, vous obtiendrez des erreurs compatibles. (L'erreur de liaison est généralement quelque chose dans le sens de: "Erreur, fonction X déjà définie dans Y") Ce que vous pouvez faire est d'utiliser le mot clé inline et vous ne violez plus l'ORD.

D'ici comment __ en ligne n'est pas standard. Contrairement à votre message, c'est généralement une extension de compilateur qui forces l'inlinisation, ne le fait pas. Inline est le mot clé standard, qui était initialement destiné à indiquer à l'inlinisation. Comme vous dites, la plupart des compilateurs modernes l'ignorent complètement à cet égard et ce n'est que des objectifs de nos jours, c'est de donner des liens internes.


5 commentaires

Toute réflexion sur ce que l'heuristique d'un compilateur moderne comme G ++ utilise dans sa décision? C'est-à-dire que c'est dans le sens des lignes de "en ligne toute fonction que le rapport des sites d'appel à des octets-in-fonction-corps est inférieur à x"? Ou est-ce quelque chose de plus subtil?


@Jeremy: Je n'ai aucune idée, bien que je suis assez intéressé maintenant que vous mentionnez. Je serai capable de regarder ce soir. Je soupçonne que c'est assez compliqué.


@Gman: le bit sur la liaison interne est incorrect. Inline n'a aucun effet sur le lien. En C ++, une fonction déclarée inline a une liaison externe (sauf indication spécifique statique ), comme n'importe quelle autre fonction. L'ODR pour les fonctions en ligne permet spécifiquement de définitions multiples dans différentes unités de traduction, même si la liaison est externe.


En d'autres termes, inline est ce mot clé péculaire qui permet de travailler autour de ODR, tout en gardant la liaison externe de la fonction. Sinon, ce ne serait différent de statique .


En effet, il a toujours une liaison externe est une clé clé de en ligne . Étant donné que la statique locale est associée à leur fonction (différente de c), inline int ID () {statique int i = ios_base :: xalloc (); retour je; } retournera le même entier indépendant de ce qu'on appelle, et peut apparaître dans les en-têtes. Ayant encore une liaison externe et la même adresse de tous les TUS, il peut également être utilisé comme arguments de modèle sur des paramètres non-types.



4
votes

du C ++ FAQ Lite :

peu importe la façon dont vous désignez une fonction comme en ligne, c'est une demande que le Le compilateur est autorisé à ignorer: pourrait en ligne - élargir certains, tous, ou aucun des appels vers une fonction inline.


0 commentaires

2
votes

Si vous Définissez une fonction avec une liaison externe dans un fichier d'en-tête et l'inclure dans plusieurs unités de traduction, vous obtiendrez une erreur de compilation (plus précisément: Linker Erorr) pour violation d'une définition Règle (ORD). La réponse est donc "non": la définition d'une fonction dans un fichier d'en-tête ne sera pas prise par Compiler comme indice d'inlinage et ne vous excusera pas d'observer les exigences de la DDR. Non seulement de telles fonctions ne sont pas garanties d'être inlinées, mais probablement votre programme ne compilera même pas.

Afin de définir une fonction dans un fichier d'en-tête et de vous en éloigner, vous devez le donner soit une liaison interne à l'indiquer (déclarez-le statique , et finissez par une fonction distincte dans chaque unité de traduction), ou expliquez explicitement celui-ci inline .

Quant aux heuristiques ... Les compilateurs modernes envisageront normalement pratiquement toutes les fonctions d'inlinisation (en appliquant des heuristiques), quel que soit l'endroit où il est défini et s'il est explicitement déclaré en ligne ou non. < / p>


0 commentaires

1
votes

Il n'y a pas de magie sur les fonctions dans les en-têtes. Le compilateur ne sait même pas si une fonction est définie dans une en-tête ou non. (Étant donné que les en-têtes sont effectivement copiants / collés dans le fichier source, vous pourriez le définir dans une en-tête, mais le compilateur vient de le voir dans le cadre de l'unité de traduction)

Il existe également deux significations différentes de "Inline" à être conscientes:

Une fonction peut être inlined telle que définie par la norme C ++: Ceci est effectué soit en préfixant la fonction avec le mot-clé inline , ou s'il s'agit d'une fonction membre, en le définissant sur place dans la définition de la classe.

L'effet de ceci est à

  • Informez le lien que cela peut rencontrer la définition de la fonction dans plusieurs fichiers, et il devrait simplement les fusionner silencieusement ensemble au lieu de lancer une erreur
  • facilite la tâche du compilateur d'effectuer l'inlinge l'optimisation .

    L'inlinçon l'optimisation est simplement l'acte de remplacer un appel de fonction par le corps de la fonction appelée, ce qui signifie que cette optimisation est en fait appliquée aux sites d'appel, et non à des fonctions. . Une fonction peut être appelée normalement des endroits, mais ailleurs ailleurs. Un appel de fonction est affiné lorsque le compilateur se sent comme celui-ci et il est préférable de le séparer conceptuellement de la séparer entièrement de la première signification de «Inline».

    Le compilateur appliquera l'optimisation de l'inlinage si, quand et où il se sent comme ça. Il utilise beaucoup d'heuristiques pour cela. Les plus petites fonctions sont plus susceptibles d'être inlinées. S'il détermine qu'un site d'appel spécifique va être exécuté suffisamment souvent, il est plus susceptible d'être inliné. En fin de compte, les heuristiques utilisées sont basées sur «améliorera-t-il ou dégrader la performance». Et c'est généralement un meilleur juge de ceci que les êtres humains. Vous n'avez donc pas besoin de savoir quelles heuristiques précises utilisées. Trop d'inliquer ne fera que nuire aux performances.


0 commentaires