9
votes

Initialisation conditionnelle d'une variable Const

Le code de base suivant fait partie d'une procédure assez importante: xxx

x n'est modifié nulle part ailleurs, je peux donc faire: xxx

mais foo () est une fonction très coûteuse et complexe, donc je ne peux donc pas l'appeler deux fois en raison de la performance et du fait qu'il peut générer un condition de la course et donc obtenir des valeurs différentes (cela peut impliquer la lecture des ressources externes).

J'aimerais apporter du code aussi lisible et, si possible, aussi court que possible. Une option est de: xxx

d'autre part, je voudrais éviter ce type de variable temporelle principalement parce que foo () peut dépendre Sur des ressources externes, vous utilisez donc foo _ comme une valeur mise en cache dans le reste du code n'est pas valide.

Je pose la solution que j'utilise maintenant mais je ' J'aime savoir s'il y a de meilleures options (aucun ou peu d'encombrement de code, aucune variables temporelle dans la même portée, lisibilité ...). Merci d'avance!

PS: il doit suivre au moins la norme C ++ 11, puisqu'il appartient à un projet multi-plateformes.

Je sais que c'est peut-être une opinion basée sur une opinion, Mais compte tenu des déclarations précédentes sur la simplicité (ne pas encombrer le code) et d'éviter les variables temporelles (pas pour la lisibilité, mais pour la sécurité du code), j'aimerais connaître des options pour résoudre ce problème.


5 commentaires

Les opérateurs ternaires peuvent sembler mieux lorsque vous les écrivez, mais lorsque vous revenez au code par mois plus tard, ils sont un cauchemar à déchiffrer, surtout si vous ne les écrivez pas vous-même. La lisibilité ne va pas toujours bien avec le code abrégé et ajouter des commentaires peut être en ordre


Veuillez expliquer pourquoi vous pensez que les variables "temporelles" entravent "la sécurité du code", en particulier plus que des "astuces" intelligentes, difficiles à comprendre?


Je suis d'accord des variables temporelles plus faciles à comprendre, je voudrais juste éviter les chances d'utiliser un état non valide en raison de l'existence d'une telle variable (mise en cache la valeur de retour de FOO () ). C'est pourquoi je pose la question, y a-t-il une chance d'avoir le meilleur des deux mondes: la lisibilité et la sécurité?


Si votre procédure est «assez grande», vous devez probablement d'abord vous concentrer sur la division que dans des procédures plus petites (si votre objectif est de la maintenabilité ...)


@chtz à coup sûr, c'est l'une des tâches que nous visons maintenant!


6 Réponses :


5
votes

La solution que j'ai trouvée jusqu'à présent est d'utiliser une fonction Lambda telle que:

const int x = [](int n) { return n == 0 ? bar() : n; }(foo());


2 commentaires

Oui, mais comme indiqué dans la question, mon problème avec des variables temporelles est dû à la nature de foo () plus qu'avec la variable temporelle elle-même (si la variable temporelle est utilisée, sa valeur peut être extérieure. de date). D'autre part, si au lieu de int J'utiliserais un type avec un copy-constructeur complexe, je le changerais avec const & .


Ceci est trop compliqué et non trivial à comprendre.



7
votes

Si vous êtes heureux d'utiliser Extensions GCC , puis vous pouvez écrire: xxx


1 commentaires

A l'air super, mais malheureusement, je dois suivre la norme car il s'agit d'un code multi-plate-forme. Je vais prendre en compte le code GCC, merci! Ce serait bien de le voir dans une norme future.



3
votes

Qu'en est-il d'un simple: xxx


4 commentaires

Merci, mais désolé, comme mentionné dans la question, j'aimerais éviter les variables temporelles.


@CBUCTART: On s'attendrait à ce qu'il soit optimisé difficile, et je le trouve moins déroutant que la Lambda.


@CBUCTART: "J'aimerais éviter les variables [temporaires]" pourquoi? C'est la solution la plus évidente, la plus pratique et la normale. Compréhensible par votre compilateur et par une personne. Et il ne devrait absolument pas avoir de pénalité d'exécution (pourquoi cela aurait-il? Vous avez la même quantité de données et de quantité d'objets)


Compte tenu de la nature de foo () , si son résultat est mis en cache dans une variable temporelle et que la variable est utilisée ultérieurement, elle peut représenter un état invalide. J'aimerais éviter cette situation.



2
votes

Outre la Lambda, et si cette situation ne se produit pas de plusieurs reprises dans votre programme, vous pouvez envelopper la fonction foo () code> avec une fonction, disons conditionnelfoo () code> :

int conditionalFoo() {
  int result = foo();
  if (result==0)
    result = bar();
  return result;
}
...
const int x = conditionalFoo();


2 commentaires

Vous pouvez utiliser la barre de retour (); dans votre fonction.


De plus, vous pouvez passer foo () comme paramètre (le rendant plus similaire à la solution d'expression Lambda proposée par OP). Ensuite, la méthode doit être nommée int conditionnelle (int FOO) peut-être.



2
votes

Étant donné que c'est une question basée sur l'opinion, j'irais avec: xxx

un bon nom au lieu de get_the_correct_x serait encore plus clair que d'essayer de jouer avec Lambdas sans nommage.


2 commentaires

Si vous utilisez beaucoup cela, je suggérerais de faire une méthode / une fonction appropriée, au lieu d'une expression de Lambda, cependant.


Jusqu'à présent, c'est la solution que je trouve plus utile, peut être plus grande que l'inline Lambda mais génère un code plus lisible, merci! Je mettra à jour la question avec la mise en œuvre finale que j'ai utilisée



3
votes

Fondamentalement, vous voulez le OPERICE ELVIS , mais C ++ n'a aucun. C'est le genre de chose que vous pourrait veux utiliser une seconde fois. Donc, au lieu de votre solution Lambda proposée, je opte pour une solution générale.

par exemple xxx

utilisé comme xxx

Si vous préférez appeler les fonctions vous-même, vous pouvez faire xxx

et l'utiliser comme xxx


0 commentaires