Question Est-ce que noexcept améliore les performances?


Est le noexcept spécificateur de fonction visant à améliorer les performances en raison de l'absence potentielle de code de tenue de livres pour les exceptions dans l'objet généré et, par conséquent, devrait être ajouté aux déclarations de fonction et aux définitions chaque fois que possible? Je pense aux enveloppes pour les objets appelables en premier lieu, où noexcept pourrait faire une différence, bien que les expressions de vérification puissent "gonfler" le code source. Est-ce pire?


23
2018-04-19 11:55


origine


Réponses:


Les meilleurs compilateurs produisent du code qui est déjà optimisé, comme le code qui ne peut pas être lancé, et le cas où une exception se produit est géré par du code hors ligne trouvé par le mécanisme de gestion des exceptions en examinant les métadonnées fonction. Je suppose que la taille du code présente certains avantages à ne pas en tenir compte quand on sait qu’elle n’est pas nécessaire.

Il existe probablement des cas où une spécification nothrow autorise une optimisation spécifique:

int main() {
    int i = 0;
    try {
        ++i;
        thing_that_cannot_throw();
        ++i;
        thing_that_can_throw();
        ++i;
    } catch (...) {}
    std::cout << i << "\n";
}

Ici, le second ++ pourrait en théorie être réorganisé avant l’appel à thing_that_cannot_throw (et i juste initialisé à 2). Le fait que ce soit en pratique est une autre affaire, car une implémentation qui garantit l’état des variables dans le débogueur ou dans la pile au-dessus d’un appel de fonction, voudrait i avoir de la valeur 1 pendant cet appel, même si c'est une variable locale non observable par aucun la norme veux dire.

Je soupçonne que les garanties nothrow sont plus précieuses pour le programmeur que pour le compilateur. Si vous écrivez un code qui offre la garantie d'exception forte, il y a généralement certaines opérations critiques que vous devez effectuer, que vous devez offrir la garantie de rémission (swaps, coups et destructeurs étant les candidats communs).


9
2018-04-19 12:45



Théoriquement parlant, noexcept améliorerait les performances. Mais cela pourrait aussi poser certains problèmes.

Dans la plupart des cas, il ne devrait pas être spécifié parce que les avantages sont trop peu nombreux pour être pris en compte et que la mise à niveau de votre code pourrait être pénible. Ce post, écrit par Andrzej, présente les raisons en détail.

Si c'est trop long, prenez simplement ces suggestions que j'en conclus:

  1. Annoter les fonctions avec noexcept si
    • ils ont été annotés avec throw() déjà,
    • ou ils sont de bons candidats (énumérés dans le post) et ne jamais jeter à coup sûr,
    • ou ils sont des constructeurs de déménagement, des affectations de déménagement dont noexcept L'annotation ne peut pas être déduite correctement par le compilateur et leurs instances sont supposées être placées dans un conteneur STL.
  2. Ne pas annoter les fonctions avec noexcept si
    • vous êtes vraiment préoccupé par la réduction des performances,
    • ou sur le risque d'appeler std::terminate,
    • ou vous n'êtes pas sûr de la nouvelle fonctionnalité,
    • ou vous avez des doutes quant à savoir si vous devez faire votre travail noexcept ou pas.

13
2018-04-19 16:43