7

是否有任何由代码导致的理解/可维护性问题,例如

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

等等。

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

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

4

16 回答 16

35

我认为这比简单地打字更令人困惑并且更难阅读。

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

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

于 2009-02-07T01:41:35.580 回答
25

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

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

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

于 2009-02-07T01:44:40.333 回答
11

三元是个好东西,我一般都提倡它的用法。

然而,你在这里所做的事情会损害它的可信度。它更短,是的,但它不必要地复杂。

于 2009-02-07T02:53:33.283 回答
10

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

if(inVar1 != 0) v.push_back(inVar1);
于 2009-02-07T01:41:26.813 回答
6

如今的编译器将使 if 与三元运算符一样快。

您的目标应该是其他软件开发人员阅读的难易程度。

我投票给

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

为什么要使用括号...因为有一天您可能想在其中放些其他东西,而括号是为您预先完成的。如今,大多数编辑无论如何都会把它们放进去。

于 2009-02-07T02:34:59.640 回答
6

您对三元运算符的使用不会给您带来任何好处,并且会损害代码的可读性。

由于三元运算符返回一个您未使用的值,因此它是奇数代码。在像您这样的情况下,使用 anif更加清楚。

于 2009-02-07T02:48:23.200 回答
5

正如评论中提到的 litb ,这不是有效的 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);
于 2009-02-07T03:38:26.313 回答
2

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

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

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

于 2009-02-07T02:39:55.527 回答
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原则,与后者不同 - 你不需要编写两条几乎相同的行。

于 2009-02-07T07:39:50.787 回答
1

我认为你最好做一个适当的 if 结构。我什至更喜欢在 if 结构中始终使用大括号,以防我稍后必须在条件执行中添加行。

if (inVar != 0) {
    v.push_back(inVar);
}
于 2009-02-07T01:44:48.710 回答
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
}

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

于 2009-02-07T21:52:23.670 回答
1

我看到的大多数受折磨的三元组(头韵如何?)只是尝试将真正属于 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 语句中会弄乱您的代码,请将其放在其他地方!

于 2009-03-08T01:14:35.283 回答
1
inVar1 != 0 || v.push_back(inVar1);
inVar2 != 0 || v.push_back(inVar2);

在 Perl 等语言中发现的常见模式。

于 2009-03-19T00:52:36.920 回答
0

如果您在一个或两个三元参数中有多个方法调用,那么它是错误的。所有代码行,无论是什么语句,都应该简短而简单,最好不要复合。

于 2009-02-07T07:50:35.587 回答
0

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

if (cond) doIt();

cond ? noop() : doIt();

而下面的步骤要好得多(无论你是否有大括号):

if (cond) {
    doIt();
}
于 2009-02-07T07:50:54.663 回答
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);

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

于 2009-03-08T01:15:46.903 回答