这是三元运算符的合理使用吗?

时间:2009-02-07 01:39:05

标签: c# c++ c ternary

是否存在由

等代码引起的任何理解/可维护性问题
inVar1 == 0 ? NULL : v.push_back(inVar1);
inVar2 == 0 ? NULL : v.push_back(inVar2);

等等。

可能令人困惑的想法是使用三元运算符来进行程序流而不是变量赋值,这是通常的解释。

我在工作中没有看到解决这种用法的编码标准,所以虽然我很乐意这样做,但我想知道是否有充分的理由不这样做。

16 个答案:

答案 0 :(得分:35)

我认为阅读比单纯打字更令人困惑,更难阅读;

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

我不得不多次扫描你的例子,以确定结果会有什么确定性。我甚至更喜欢单行if(){}语句而不是你的例子 - 我讨厌单行if语句:)

答案 1 :(得分:25)

三元运算符旨在返回一个值。

IMO,它不应该改变状态,应该使用返回值。

在另一种情况下,使用if语句。如果语句用于执行代码块。

答案 2 :(得分:11)

三元是一件好事,我通常会提升它的用法。

你在这里做的事情却玷污了它的可信度。它更短,是的,但它不必要地复杂化。

答案 3 :(得分:10)

我认为应该避免这种情况。您可以在其位置使用1行if语句。

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

答案 4 :(得分:6)

这些天的编译器会像三元运算符一样快。

您的目标应该是让其他软件开发人员阅读起来有多容易。

我投票赞成

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

为什么括号...因为有一天你可能想在那里放一些东西,并且为你预先做了括号。如今,大多数编辑都将把它们放进去。

答案 5 :(得分:6)

您对三元运算符的使用不会让您受到任何影响,并且会损害代码的可读性。

由于三元运算符返回的值不是你使用的,所以奇数代码。在像你这样的情况下,使用if会更加明确。

答案 6 :(得分:5)

如评论中提到的那样isn't valid C++。例如,GCC将在此代码上发出错误:

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

但是,这可以通过强制转换来解决:

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

但成本是多少?为了什么目的?

在这种情况下,使用三元运算符不像if语句更简洁:

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

答案 7 :(得分:2)

虽然在实践中,我同意那些阻止这种写作的人的观点(在阅读时,你必须做额外的工作来扫描表达的副作用),我想提供

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

...如果你想要晦涩难懂,那就是。 GCC允许x ?: y代替x ? x : y。 : - )

答案 8 :(得分:2)

当我需要使用条件参数调用某个函数时,我使用三元运算符 - 在这种情况下,它比if更好。

比较

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

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

我发现前者更具吸引力。它符合DRY原则,不像后者 - 你不需要写两条几乎相同的行。

答案 9 :(得分:1)

我认为你做一个合适的if结构会更好。我甚至更喜欢总是使用if结构的大括号,如果我必须稍后在条件执行中添加行。

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

答案 10 :(得分:1)

我认为有时候三元组是构造函数的初始化列表中必不可少的恶。我主要将它们用于构造函数,在那里我想分配内存并设置一些指针指向构造函数体之前的指针。

一个例子,假设您有一个整数存储类,您希望将一个向量作为输入,但内部表示是一个数组:

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
}

这就是我使用三元运算符的方法。我不认为它像某些人那样令人困惑,但我认为应该限制他们使用它的程度。

答案 11 :(得分:1)

我看到的大多数受折磨的三元组(如何用于头韵?)仅仅是试图将if语句真正属于if语句的逻辑放在if语句不属于或不能去的地方。

例如:

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

假设v.push_back是无效的,但是如果它返回一个需要传递给另一个函数的值呢?在这种情况下,它必须看起来像这样:

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

但是,对于如此简单的代码,这更需要消化。我的解决方案:定义另一个函数。

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));

无论如何,重点在于:如果你有一些逻辑对于三元组而言太过折磨,但是如果把它放在if语句中会使你的代码混乱,那就把它放在其他地方!

答案 12 :(得分:1)

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

在Perl等语言中找到的常见模式。

答案 13 :(得分:0)

如果你在一个或两个tenary参数中有多个方法调用,那么它是错误的。所有代码行都不管什么语句应该简短,理想情况下不能复合。

答案 14 :(得分:0)

正如其他人所提到的那样,正确的if语句更具可读性。此外,当您使用调试器单步执行代码时,如果所有内容都在一行中或者您使用的是三元表达式,则无法轻松查看if的哪个分支:

if (cond) doIt();

cond ? noop() : doIt();

以下是更好的步骤(无论你是否有括号):

if (cond) {
    doIt();
}

答案 15 :(得分:0)

如前所述,它不比1行if语句更短或更清晰。然而,它也不再 - 而且并不是那么难以理解。如果您了解三元运算符,那么很明显发生了什么。

毕竟,如果被分配给变量,我认为没有人会遇到问题(即使它也是变异状态):

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

三元运算符总是返回一个值 - IMO - 这一事实无关紧要。当然没有要求您使用所有返回值...毕竟,赋值返回一个值。

话虽如此,如果我使用NULL分支运行它,我会用if语句替换它。

但是,如果它替换了3行if语句:

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

使用:

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

可能离开它......取决于我的心情。 ;)