这是 ?三元运算合法吗?

Posted

技术标签:

【中文标题】这是 ?三元运算合法吗?【英文标题】:Is this ? ternary operation legal? 【发布时间】:2022-01-17 08:20:03 【问题描述】:

我不是专家,但我喜欢学习和理解。考虑到这一点,我在 Arduino IDE 中编写了以下内容:

lockout[idx] ? bulb[idx].off() : bulb[idx].on();

替换这个:

if (lockout[idx]) bulb[idx].off(); else bulb[idx].on();

lockout[]bool 的数组,bulb[] 是一个类的数组,具有 .off.on 方法。

我四处寻找示例,但从未见过? 三元运算符的这种用法。我读到的内容似乎说这不应该起作用。

但它确实可以编译。那么这实际上是合法的 C++ 吗?

【问题讨论】:

只要 off() 和 on() 返回一些东西(不是 void)并且这两个值是兼容的,它就可以工作。通常以某种方式使用三元的输出(例如分配给变量或其他东西)。这不是惯用语。 这并不意味着您应该以这种方式实际使用它。这是丑陋的、具有误导性的,并且可能会在未来产生问题。 @offtkp no ? 不只是扩展到if else。计算返回类型有一些细微的差别,可能会让你措手不及。 C++“扩展”到其他 C++ 的情况很少。我所知道的唯一一个“真正的”是for(:) 循环。其他情况(lambdas,更专业的模板等)在标准中充满了软糖词。同时,?: 不是根据if else 定义的。现在,你说的是一个有用的谎言,但是当你说这些有用的谎言时,你应该尽量弄清楚这一点。 @Offtkp — 这是对 ?: 所做的非常具有误导性的描述。这是一个表达式,所以它有一个值。 if … else … 是一个声明。它没有价值。表达式和语句是根本不同的东西。 除了编译器错误之外,如果 C++ 编译器成功编译,它通常会证明是合法的 C++(尽管它可能具有未定义的行为)。也就是说,如果lockout[idx] 可以转换为数字类型,并且bulb[idx].off()bulb[idx].on() 都有效并且返回相同的类型,那么lockout[idx] ? bulb[idx].off() : bulb[idx].on() 绝对是一个有效的表达式。 【参考方案1】:

如果它编译,它可能是格式良好的代码。如果三元运算符由于它们的类型而不能与这些操作数一起使用,编译器将发出错误消息。没有此类错误消息的事实表明您的代码不存在此类问题。

但是,在某些情况下,使用三元运算符可能会导致意外复制。

如果onoff 方法都返回void(或者说,bool),则不会出现任何复制问题,并且代码将按预期工作:如果lockout[idx] 是true 那么bulb[idx].off() 将被评估,否则bulb[idx].on() 将被评估。将只评估两个备选方案中的一个,就像 if 语句会发生的情况一样。

通常,当您需要将结果作为表达式时,会使用三元运算符。否则,使用if 语句编写代码通常更具可读性。

【讨论】:

【参考方案2】:

是的,这是合法的 C++。虽然该运算符通常称为 三元运算符,但在 C++ 标准中称为 条件运算符,并在名为“expr.cond”的部分中定义。

C++ 标准明确规定第二个和第三个操作数的类型都可以是void。因此,标准编写者知道人们可能希望使用此运算符作为编写 if 语句的捷径,就像您正在做的那样。

如果第二个或第三个操作数的类型不是void,那么标准规定“尝试将这些操作数中的每一个转换为另一个的类型”,并详细说明了这意味着什么。

作为参考,我指的 C++ 标准的版本是 N4296,所以它有点旧,但我认为这并不重要。

【讨论】:

以上是关于这是 ?三元运算合法吗?的主要内容,如果未能解决你的问题,请参考以下文章

这是合法的引用可打印编码吗?

这是合法的模板 lambda 语法吗?

这是对关联的合法使用吗?

这是合法的javascript吗?将参数传递给函数并让它改变它们

表达式 x---y 是如何解析的?是合法的表达吗?

PHP - 使用自定义标签进行模板化 - 这是对 eval 的合法使用吗?