2017-03-02 4 views
2

Disons que j'ai une fonction inline comme this:Comment le compilateur gère-t-il la fonction inline?

inline double CalculateValue() { 
    // some condition 
    if (true) { 
     // some other condition 
     if (true) { 
      // another condition 
      if (true) { 
       return 1.0; 
      } 

      // somethings 
      std::cout << "inside1" << std::endl; 
     } 

     // somethings 
     std::cout << "inside2" << std::endl; 
    } 

    return 2.0; 
} 

void Process() { 
    double value = CalculateValue(); 

    value *= 100.0; 

    std::cout << value << std::endl; 
} 

int main() 
{ 
    Process(); 
} 

Il sera « copier-coller » la fonction CalculateValue() dans le Process() un. Le résultat est 100, comme prévu.

Mais si j'essaie de emulate comment cette « copier-coller » sera réalisée, il y a quelque chose que je ne comprends pas:

void Process() { 
    double value; 

    // some condition 
    if (true) { 
     // some other condition 
     if (true) { 
      // another condition 
      if (true) { 
       value = 1.0; 
       return; 
      } 

      // somethings 
      std::cout << "inside1" << std::endl; 
     } 

     // somethings 
     std::cout << "inside2" << std::endl; 
    } 

    value = 2.0; 

    value *= 100.0; 

    std::cout << value << std::endl; 
} 

int main() 
{ 
    Process(); 
} 

Bien sûr, quand il atteint l'instruction return, le reste de la fonction doit être ignoré (c.-à-d. inside1 et inside2 ne doit jamais être imprimé), à cause du return. Mais si je return de la fonction parente (Process()), il revient immédiatement, donc je ne peux jamais voir 100.

Cela signifie qu'il le fait d'une autre manière.

Comment le compilateur gère-t-il cette situation? J'ai essayé de créer un bloc de code, mais toujours le return retourne à la fonction principale ...

+1

Le compilateur n'utilise évidemment pas de retour, je ne sais pas exactement lequel est utilisé, mais il y a beaucoup d'autres options comme ' tandis que (1) {... break; } 'ou même' goto' ou des étapes plus obscures avec asm – slawekwin

+0

'inline' ne change pas la sémantique d'un appel de fonction, seulement son lien. – sp2danny

Répondre

2

En écrivant votre "émulation" vous avez oublié de manipuler un des return s. Dans une fonction inline, le compilateur devrait le remplacer par une instruction goto.

void Process() { 
    double value; 

    // begin of inlined function 

    // some condition 
    if (true) { 
     // some other condition 
     if (true) { 
      // another condition 
      if (true) { 
       value = 1.0; 
       goto next;  // <<<<<<<<<<<<<<<<<<< return replaced by goto 
      } 

      // somethings 
      std::cout << "inside1" << std::endl; 
     } 

     // somethings 
     std::cout << "inside2" << std::endl; 
    } 

    value = 2.0; 
next: 
    //end of inlined function 

    value *= 100.0; 

    std::cout << value << std::endl; 
} 
+1

Est-ce que 'goto' n'est pas mauvais pour la programmation? :) – markzzz

+0

Selon vous, que se passe-t-il derrière «if-then-else»? 'goto' n'est pas mauvais * en soi * (comme un couteau), seuls ses usages peuvent être bons ou mauvais. –

+0

@ Le commentaire de Jean-BaptisteYunès paizza était probablement ironique. –

0

Dans ce cas, le code inline traiterait la return plus comme un goto, par exemple:

void Process() { 
    double value; 

    // some condition 
    if (true) { 
     // some other condition 
     if (true) { 
      // another condition 
      if (true) { 
       value = 1.0; 
       goto nextStep; 
      } 

      // somethings 
      std::cout << "inside1" << std::endl; 
     } 

     // somethings 
     std::cout << "inside2" << std::endl; 
    } 

    value = 2.0; 

nextStep: 

    value *= 100.0; 

    std::cout << value << std::endl; 
} 

Le processus de inline est plus qu'un simple « copier-coller », le code résultant a pour donner un sens au code dans lequel il est injecté. Le compilateur est libre de modifier et d'optimiser le code en ligne si nécessaire tout en conservant la sémantique du code original