33 votes

Pourquoi devrais-je jamais utiliser du code en ligne?

Je suis développeur C / C ++, et voici quelques questions qui m'ont toujours dérouté.

  • Y a-t-il une grande différence entre le code "normal" et le code en ligne?
  • Quelle est la principale différence?
  • Le code en ligne est-il simplement une "forme" de macros?
  • Quel type de compromis doit être fait lors du choix d'inclure votre code?

Merci

45voto

Konrad Rudolph Points 231505

Performance

Comme cela a été suggéré dans les réponses précédentes, inline peut rendre le code plus rapide, souvent au détriment de l'augmentation des exécutables. Cependant, les compilateurs modernes sont très bons à l'in-lining automatiquement sans aucune demande de l'utilisateur lorsque la valeur haute de l'optimisation. En fait, les compilateurs sont généralement mieux à la détermination de quoi en ligne pour un gain de vitesse que l'homme.

Déclarer les fonctions inline explicitement par souci de gain de performance est (presque) toujours inutile!

En outre, les compilateurs peuvent et vont ignorer l' inline demande si elle leur convient. Compilateurs de le faire si la fonction est difficile à inline (c'est à dire à l'aide non négligeable de la récursivité ou des pointeurs de fonction), mais aussi si la fonction est tout simplement trop grand pour être correctement insérée.

Une Définition De La Règle

Toutefois, la déclaration d'une fonction inline peut effectivement être nécessaire pour des raisons complètement différentes, à savoir satistfy Une Définition de la Règle (ODR). Cette règle dans la norme C++ indique qu'un symbole donné peut être déclaré plusieurs fois, mais ne peut être défini une fois pour toute. Si l'éditeur de liens (= de l'éditeur de liens) rencontre plusieurs identiques définitions de symboles, il va générer une erreur.

Une solution à ce problème est de faire en sorte qu'une unité de compilation n'est pas à l'exportation d'un symbole donné par le marquant static (static – le mot-clé le plus complètement sans rapport avec les significations en C).

Cependant, il est souvent préférable de marquer une fonction inline à la place. Ainsi, vous permettent au compilateur de ne pas créer la définition de la fonction à tous. C'est souvent très utile lorsque vous travaillez avec des modèles qui, habituellement, doivent être déclarés dans les fichiers d'en-tête.

Par exemple, considérons le programme suivant:

// header.hpp
#include <iosfwd> // for std::ostream&

#ifndef HEADER_HPP
#define HEADER_HPP

template <typename IteratorT>
/*inline*/ void print_all(IteratorT begin, IteratorT end, std::ostream& out, char sep = ' ') {
    while (begin != end)
        out << *begin++ << sep;
}

#endif // !defined(HEADER_HPP)


// test.cpp
#include <iostream>
#include <vector>
#include "header.hpp"

void test_function() {
    using namespace std;
    vector<int> vec;
    int x;
    while (cin >> x) vec.push_back(x);
    cout << "Results: ";
    print_all(vec.begin(), vec.end());
    cout << endl;
}


// main.cpp
#include <iostream>
#include <vector>
#include "header.hpp"

void test_function(); // Forward declaration.

int main() {
    using namespace std;
    vector<int> xyz(23, 42);
    print_all(xyz);
    cout << endl << "Test call:" << endl;
    test_function();
}

Notez que les deux .cpp fichiers inclure le fichier d'en-tête et donc la définition de la fonction d' print_all. Bien que le fichier est enregistré avec comprenant des protections contre la double inclusion, cela entraîne deux définitions de la même fonction, mais dans les différentes unités de compilation.

Maintenant, si vous essayez de lier les deux unité de compilation, disons, à l'aide de la commande suivante:

$ g++ -Wall -pedantic main.cpp test.cpp

vous recevrez un message d'erreur disant "double définition de l' print_all" ou quelque chose de similaire. Si, toutefois, vous " de la inline modificateur en face de la définition de la fonction, le code compile et les liens correctement.

41voto

Luc Touraille Points 29252
  • Est-il une grande différence entre "régulier" de code et le code en ligne?

Oui et non. Non, parce que d'une fonction en ligne ou la méthode a exactement les mêmes caractéristiques qu'un régulièrement un, le plus important étant qu'ils sont tous deux de type sécuritaire. Et oui, parce que le code assembleur généré par le compilateur sera différent; avec une fonction régulière, chaque appel sera traduit en plusieurs étapes: pousser les paramètres sur la pile, de faire le saut à la fonction, à éclater les paramètres, etc, alors qu'un appel à une fonction inline sera remplacée par son propre code, comme une macro.

  • Est code en ligne tout simplement d'une "forme" de macros?

Pas de! Une macro est simple de remplacement de texte, ce qui peut conduire à des erreurs graves. Considérons le code suivant:

#define unsafe(i) ( (i) >= 0 ? (i) : -(i) )

[...]
unsafe(x++); // x is incremented twice!
unsafe(f()); // f() is called twice!
[...]

À l'aide d'une fonction en ligne, vous êtes sûr que les paramètres seront évalués avant que la fonction est effectivement réalisé. Ils pourront également être vérifié et éventuellement converties pour correspondre aux paramètres formels types.

  • Quel genre de compromis doit être fait lors du choix de l'inclure votre code?

Normalement, l'exécution du programme devrait être plus rapide lors de l'utilisation de fonctions inline, mais avec un plus gros code binaire. Pour plus d'informations, vous devriez lire GoTW#33.

16voto

Sander Points 9804

Code en ligne fonctionne comme les macros en essence, mais il est vrai code, ce qui peut être optimisé. Très petites fonctions sont souvent bons pour l'in-lining, car le travail nécessaire pour mettre en place l'appel de la fonction (charger les paramètres dans les registres appropriés) est coûteux par rapport à la petite quantité de travail effectif la méthode. Avec l'in-lining, il n'est pas nécessaire de configurer l'appel de la fonction, parce que le code est directement collé dans" la méthode qu'il utilise.

Inline augmente la taille du code, qui est son principal inconvénient. Si le code est tellement grand qu'il ne peut pas tenir dans le cache du PROCESSEUR, vous pouvez obtenir d'importants ralentissements. Vous avez seulement besoin de s'inquiéter à ce sujet dans de rares cas, puisqu'il n'est pas probable que vous êtes en utilisant une méthode dans de nombreux endroits de l'augmentation de code de causerait des problèmes.

En résumé, d'inlining est idéal pour accélérer les petites méthodes qui sont appelées plusieurs fois, mais pas dans de trop nombreux endroits (100 places est toujours très bien, cependant, vous devez aller dans pas mal d'exemples extrêmes pour obtenir de l'importante augmentation du code).

Edit: comme d'autres l'ont souligné, d'inlining n'est qu'une suggestion pour le compilateur. Il peut librement ignorer vous si il pense à vous rendre stupide demandes comme l'in-lining un énorme 25-méthode de la ligne.

7voto

Adam Davis Points 47683
  • Est-il une grande différence entre "régulier" de code et le code en ligne?

Oui - code en ligne n'implique pas un appel de fonction, et d'économie d'enregistrer des variables de la pile. Il utilise le programme de l'espace à chaque fois qu'il est "appelé". L'ensemble de sorte qu'il faut moins de temps pour s'exécuter, car il n'y a pas de ramification dans le processeur et la sauvegarde de l'état, de la compensation des caches, etc.

  • Est code en ligne tout simplement d'une "forme" de macros?

Les Macros et le code en ligne présentent des similitudes. la grande différence est que le code en ligne est formaté de manière spécifique en fonction de sorte que le compilateur, et les futurs responsables, ont plus d'options. Plus précisément, il peut facilement être transformée en une fonction de si vous dire au compilateur d'optimiser du code de l'espace, ou d'un futur responsable finit par l'expansion et de l'utiliser dans de nombreux endroits dans leur code.

  • Quel genre de compromis doit être fait lors du choix de l'inclure votre code?

    • Macro: haute code de l'espace d'utilisation, rapide d'exécution, difficile à maintenir si la "fonction" est long
    • Fonction: faible code d'utilisation de l'espace, plus lent à l'exécution, facile à entretenir
    • Fonction Inline: haute code d'utilisation de l'espace, l'exécution rapide, facile à entretenir

Il convient de noter que le registre d'économie et de sauter à la fonction prend code de l'espace, de sorte que pour de très petites fonctions inline peut prendre moins d'espace que dans une fonction.

-Adam

2voto

PhiLho Points 23458

Il dépend du compilateur...
Disons que vous avez un idiot du compilateur. En indiquant une fonction doit être insérée, elle va mettre une copie du contenu de la fonction sur chaque événement, il est appelé.

Avantage: pas d'appel de fonction, les frais généraux (en mettant les paramètres, en poussant le PC actuel, le saut à la fonction, etc.). Peut être importante dans la partie centrale d'une grande boucle, par exemple.

Inconvénients: gonfle le binaire généré.

Est-ce qu'une macro? Pas vraiment, car le compilateur vérifie toujours le type de paramètres, etc.

Ce sujet de smart compilateurs? Ils peuvent ignorer la ligne directive, s'ils "se sentent" la fonction est trop complexe ou trop grand. Et peut-être qu'ils peuvent automatiquement inline certains trivial fonctions, comme la simple getters/setters.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X