2017-08-18 1 views
4

Tenir compte de cette fonction:Comment vérifier si l'optimisation de la valeur de retour s'est produite?

std::string 
myClass::myFunction2() { 
    std::string result = myClass::myFunction1(); 
    return result; 
} 

J'espère que la compilation exécute return value optimization. Comment puis-je m'assurer que cela se produise réellement, et le code ne copiera pas le résultat de manière redondante?

+2

'g ++ -S' est votre ami: https://stackoverflow.com/questions/137038/how-do-you-get-assembler-output-from-cc-source-in-gcc – NPE

+5

Votre premier problème est votre code d'exemple n'est pas légal C++; Je peux remplir des espaces vides (créer du code pour corriger vos erreurs de construction), mais différents blancs mènent à des conclusions différentes, donc je refuse de le faire. Post code réel pas pseudocode. Votre deuxième problème est que les compilateurs, auxquels on ne leur dit pas explicitement de ne pas le faire, se passeront s'ils le peuvent, et les règles pour quand ils le peuvent sont simples. Votre troisième problème est attentionné, car même s'il n'est pas élidé, le coût d'un mouvement de chaîne est petit et limité. Sauf profilage qui est; et si vous profilez et examinez l'assemblage aux points chauds, vous saurez. (Ce qui précède ne sera pas un point chaud) – Yakk

+0

Utilisez C++ 11 et versions ultérieures, et renvoyez les types qui ont un constructeur de mouvement valide. En C++ 11, grâce à la sémantique des déplacements, la norme est capable d'imposer l'élision des temporels - y compris RVO - dans certains cas. Tant que vous respectez les cas spécifiés dans la norme, tout ira bien. Avant C++ 11, il n'était pas possible de forcer un compilateur à effectuer RVO de quelque façon que ce soit - le support ou non par un compilateur était une "qualité d'implémentation", puisque la norme autorisait mais ne nécessitait pas RVO, donc les compilateurs dois le faire. – Peter

Répondre

3

RVO est toujours appliqué, si possible. Dans votre cas, en supposant que myFunction1() ne renvoie pas d'objets nommés différents en fonction du chemin d'exécution, le compilateur doit effectuer RVO. Si elle renvoie différents objets nommés avec un chemin d'exécution différent, le compilateur n'est pas en mesure d'effectuer l'optimisation.

Je recommande de faire vos propres expériences:

Pour désactiver l'optimisation partout, utilisez pragma:

#pragma GCC push_options 
#pragma GCC optimize (ARG) 

//your code 

#pragma GCC pop_options 

Pour désactiver l'optimisation pour une fonction spécifique, utilisez __attribute __ (()):

void __attribute__((optimize(ARG))) foo(unsigned char data) { 
    // your code 
} 

ARG peut être soit des nombres (c.-à-d. un niveau d'optimisation) ou des chaînes commençant par 0 (une option d'optimisation) etc. Pour ce dont vous avez besoin, vous pouvez substituer ARG avec "O0" Ensuite, exécutez les deux versions de votre code en utilisant gcc -S pour voir la différence. Je vous recommande de lire gcc 4.4 ou plus récent doc.