Question

Y a-t-il des problèmes de compréhension / maintenabilité qui résultent de code comme

inVar1 == 0 ? NULL : v.push_back(inVar1);
inVar2 == 0 ? NULL : v.push_back(inVar2);

et ainsi de suite.

L'idée peut-être source de confusion utilise l'opérateur ternaire pour le déroulement du programme plutôt que l'affectation des variables, ce qui est l'explication habituelle.

Je ne l'ai pas vu des normes de codage au travail qui traitent de cet usage, donc pendant que je suis à l'aise de faire ce que je voudrais savoir s'il y a une bonne raison de ne pas.

Était-ce utile?

La solution

Je pense qu'il est source de confusion et beaucoup plus difficile à lire que de taper simplement;

if (inVar != 0)
  v.push_back(inVar);

Je devais analyser votre exemple plusieurs fois pour comprendre ce que le résultat serait avec certitude. Je dirais même préfère une seule ligne if () {} déclaration que votre exemple - et je déteste monoligne instruction if:)

Autres conseils

L'opérateur ternaire est censé renvoyer une valeur.

OMI, il ne devrait pas muter état, et la valeur de retour doit être utilisé.

Dans l'autre cas, utiliser si des déclarations. Si les déclarations sont destinées à exécuter des blocs de code.

Le ternaire est une bonne chose, et je promouvoir généralement son usage.

Qu'est-ce que vous faites ici ternit la crédibilité mais il est. Il est plus court, oui, mais il est inutilement compliqué.

Je pense que cela devrait être évité. Vous pouvez utiliser une ligne 1 instruction if à sa place.

if(inVar1 != 0) v.push_back(inVar1);

COMPILATEURS ces jours-ci fera une si aussi rapide qu'un opérateur ternaire.

objectif devrait être est-il facile à lire pour un autre développeur de logiciel.

Je vote pour

if ( inVar != 0 )
{
   v.push_back( inVar );
}

pourquoi les parenthèses ... parce qu'un jour vous voudrez peut-être mettre quelque chose d'autre là-bas et les supports sont pré-faites pour vous. La plupart des éditeurs ces jours-ci vont les mettre dans de toute façon.

Votre utilisation de l'opérateur ternaire vous ne gagne rien et vous blesser la lisibilité des codes.

Depuis l'opérateur ternaire retourne une valeur que vous ne l'utilisez pas est un code étrange. L'utilisation d'un if est beaucoup plus clair dans un cas comme le vôtre.

Comme mentionné litb dans les commentaires, cette n'est pas C ++ valide . GCC, par exemple, émet une erreur sur ce code:

error: `(&v)->std::vector<_Tp, _Alloc>::push_back [with _Tp = int, _Alloc =
std::allocator<int>](((const int&)((const int*)(&inVar1))))' has type `void' 
and is not a throw-expression

Toutefois, cela peut être contourné par coulée:

inVar1 == 0 ? (void)0 : v.push_back(inVar1);
inVar2 == 0 ? (void)0 : v.push_back(inVar2);

Mais à quel prix? Et dans quel but?

Il est pas comme utilisant l'opérateur ternaire ici est plus concise qu'une instruction if dans cette situation:

inVar1 == 0 ? NULL : v.push_back(inVar1);
if(inVar1 != 0) v.push_back(inVar1);

Alors que, dans la pratique, je suis d'accord avec les sentiments de ceux qui découragent ce type d'écriture (lors de la lecture, vous devez faire un travail supplémentaire pour analyser l'expression de ses effets secondaires), je voudrais offrir

!inVar1 ?: v.push_back(inVar1);
!inVar2 ?: v.push_back(inVar2);

... si vous allez pour obscur, c'est. GCC permet x ?: y en place de x ? x : y. : -)

J'utilise l'opérateur ternaire quand je dois appeler une fonction avec des arguments conditionnels -. Dans ce cas, il vaut mieux alors if

Comparer:

printf("%s while executing SQL: %s",
        is_sql_err() ? "Error" : "Warning", sql_msg());

avec

if (is_sql_err())
    printf("Error while executing SQL: %s", sql_msg());
else
    printf("Warning while executing SQL: %s", sql_msg());

Je trouve que le premier est plus attrayant. Et il est conforme DRY principe , contrairement à ce dernier - vous n'avez pas besoin d'écrire deux presque identiques des lignes.

Je pense que vous seriez mieux servi à faire une bonne si la structure. Je préfère même d'avoir toujours des accolades avec mes si des structures, en cas je dois ajouter des lignes plus tard à l'exécution conditionnelle.

if (inVar != 0) {
    v.push_back(inVar);
}

Je pense que parfois le ternaire sont un mal nécessaire dans les listes de initialiseur pour les constructeurs. Je les utilise surtout pour les constructeurs où je veux allouer de la mémoire et définir un certain pointeur vers point avant que le corps du constructeur.

Par exemple, supposons que vous aviez une classe de stockage entier que vous vouliez avoir prendre un vecteur comme une entrée, mais la représentation interne est un tableau:

class foo
{
public:
    foo(std::vector<int> input);
private:
    int* array;
    unsigned int size;
};

foo:foo(std::vector<int> input):size(input.size()), array( (input.size()==0)?
        NULL : new int[input.size])
{
    //code to copy elements and do other start up goes here
}

Voici comment j'utiliser l'opérateur ternaire. Je ne pense pas qu'il est aussi confus que certaines personnes ne mais je ne pense que l'on devrait limiter la quantité qu'ils utilisent.

La plupart des ternaires torturées (comment est-ce pour allitération?) Je vois des tentatives simplement à mettre la logique qui appartient vraiment dans une instruction if dans un endroit où une instruction if n'appartient pas ou ne peut pas aller.

Par exemple:

if (inVar1 != 0)
  v.push_back(inVar1);
if (inVar2 != 0)
  v.push_back(inVar2);

Les travaux en supposant que v.push_back est vide, mais si elle est de retour une valeur qui doit se passer à une autre fonction? Dans ce cas, il faudrait ressembler à ceci:

SomeType st;
if (inVar1 != 0)
  st = v.push_back(inVar1);
else if (inVar2 != 0)
  st = v.push_back(inVar2);
SomeFunc(st);

Mais c'est plus à digérer pour un simple morceau de code. Ma solution:. Définir une autre fonction

SomeType GetST(V v, int inVar1, int inVar2){
    if (inVar1 != 0)
      return v.push_back(inVar1);
    if (inVar2 != 0)
      return v.push_back(inVar2);        
}

//elsewhere
SomeFunc(GetST(V v, inVar1, inVar2));

En tout cas, le point est ceci: si vous avez une certaine logique qui est trop torturé pour un ternaire mais encombrer votre code s'il est mis dans une instruction if, mettez un autre endroit

inVar1 != 0 || v.push_back(inVar1);
inVar2 != 0 || v.push_back(inVar2);

modèle commun dans les langages comme Perl.

Si vous avez plusieurs invocations de méthode dans l'une ou l'autre des arguments tenary alors son tort. Toutes les lignes de code, quel que soit ce que la déclaration devrait être courte et simple, idéalement pas des menaces.

Une bonne instruction if est plus lisible, comme d'autres l'ont mentionné. En outre, quand vous faites un pas dans votre code avec un débogueur, vous ne serez pas en mesure de voir facilement quelle branche d'un si est pris lorsque tout est en une ligne ou vous utilisez une expression ternaire:

if (cond) doIt();

cond ? noop() : doIt();

Alors que ce qui suit est beaucoup plus agréable à parcourir (si vous avez les accolades ou non):

if (cond) {
    doIt();
}

Comme mentionné précédemment, ce n'est pas plus ou moins claire qu'une ligne 1 instruction if. Cependant, il est également plus - et n'est pas vraiment difficile à GROK. Si vous connaissez l'opérateur ternaire, il est assez évident ce qui se passe.

Après tout, je ne pense pas que quiconque aurait un problème si elle était affectée à une variable (même si elle était l'état mute ainsi):

var2 = inVar1 == 0 ? NULL : v.push_back(inVar1);

Le fait que l'opérateur ternaire retourne toujours une valeur - OMI - est hors de propos. Il n'y a certainement pas nécessaire que vous utilisez toutes les valeurs de retour ... après tout, une mission retourne une valeur.

Cela étant dit, je le remplace par une instruction if si je courais à travers avec une branche NULL.

Mais , si elle remplace une ligne 3 instruction if:

if (inVar == 0) {
   v.doThingOne(1);
} else {
   v.doThingTwo(2);
}

avec:

invar1 == 0 ? v.doThingOne(1) : v.doThingTwo(2);

peut laisser ... en fonction de mon humeur. ;)

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top