条件语句中逗号的优点是什么?
我们可以写一个if
语句
if (a == 5, b == 6, ... , thisMustBeTrue)
只有最后一个条件才可以进入if
体。
为什么允许?
稍微改变你的例子,假设是这样的
if ( a = f(5), b = f(6), ... , thisMustBeTrue(a, b) )
(注意=
而不是==
)。 在这种情况下,逗号保证从左到右的评估顺序。 相反,与此
if ( thisMustBeTrue(f(5), f(6)) )
你不知道在f(6)
之前或之后是否调用f(6)
。
更正式的说,逗号允许你用同样的方式写一个expression式(a,b,c)
写一个陈述序列a; b; c;
a; b; c;
。 就像一个;
创build一个序列点 (完整expression式的结尾),逗号也一样。 只有顺序点pipe理评估的顺序,看到这个职位 。
当然,在这种情况下,你实际上是这样写的
a = f(5); b = f(6); if ( thisMustBeTrue(a, b) )
所以,当一个逗号分隔的expression式序列更喜欢a ;
分开的语句序列? 我几乎从不说。 也许在macros观上,当你希望右边的replace是一个单一的expression式。
简而言之:虽然这样做是合法的,但在if
或while
语句的条件部分中使用逗号运算符通常没有意义(编辑:虽然后者有时可能会有所帮助,因为user5534870在他的回答中解释) 。
一个更详细的解释:除了它的语法function(例如,在初始化列表,variables声明或函数调用/声明中分离元素),在C和C ++中,
它们也可以像普通的运算符一样,所以它可以是在任何地方都可以使用expression式(在C ++中,甚至可以重载)。
与大多数其他操作符的不同之处在于,尽pipe双方都得到了评估,但它并不以任何方式组合左右expression式的输出,只是返回正确的结果。
它被引入了,因为有人(可能是Dennis Ritchie)由于某种原因决定了C需要一个语法来在一个位置写两个(或更多)不相关的expression式,通常只能写一个expression式。
现在, if
语句的条件是(除其他之外)这样一个地方,因此,你也可以在那里使用,
操作符 – 这样做是否合理是一个完全不同的问题! 特别是 – 与例如函数调用或variables声明不同,逗号在那里没有特殊的含义,所以它总是这样做:它将expression式评估到左侧和右侧,只是返回正确的结果,然后由if
语句使用。
我现在可以想到的只有两点:使用( 非重载 )操作符的意义在于:
-
如果你想在
for
循环的头部增加多个迭代器:for ( ... ; ... ; ++i1, ++i2){ *i2=*i1; }
-
如果要在C ++ 11 constexpr函数中评估多个expression式。
再次重复一遍:在if
或while
语句中使用逗号运算符 – 以您在示例中显示的方式 – 不是明智的做法。 这只是C和C ++的语言语法允许你编写代码的另一个例子,它并不像一个乍看之下那样行事。 还有更多….
对于if
语句,将某些东西放入逗号expression式而不是外部是没有意义的。
对于while
语句,将逗号expression式放入条件中会在进入循环或循环时执行第一部分。 没有代码重复就不容易复制。
那么如何… …声明呢? 我们只需要担心循环本身,对吧? 事实certificate,即使在这里,一个逗号expression式也不能通过将第一部分移动到循环中来安全地replace。
首先,循环体中的variables的析构函数将不会被运行,这可能会有所作为。 另一方面,循环内的任何continue
语句只有在确实处于条件而不是循环体时才会到达逗号expression式的第一部分。
没有优势 :逗号运算符只是expression式列表中最后一个expression式types的expression式,if语句计算布尔expression式。
if(<expr>) { ... } with type of <expr> boolean
这是一个奇怪的操作符是真实的,但它没有什么魔力 – 除了在函数调用中混淆expression式列表和参数列表。
foo(<args>) with <args> := [<expr>[, <expr>]*]
请注意,在参数列表中,逗号与分隔参数的关系更强。
接下来的是一段时间,取决于你可能希望成为多么狡猾。
考虑一个函数通过修改一个由引用传递的参数或通过一个指针(可能来自一个devise错误的库,或者为了确保这个值在返回后不被忽略而不被忽略)而返回一个值的情况。
void calculateValue(FooType &result) {/*...*/}
那么如何使用依赖于result
条件语句呢?
你可以声明将被修改的variables,然后用if来检查它:
FooType result; calculateValue(result); if (result.isBared()) { //... }
这可以缩短到
FooType result; if (calculateValue(result) , result.isBared()) { //... }
这不是真的值得。 但是 , while
循环可能有一些小的优点。 如果calculateValue
应该/可以调用,直到结果不再是bar'd,我们会有这样的:
FooType result; calculateValue(result); //[1] Duplicated code, see [2] while (result.isBared()) { //... possibly many lines //separating the two places where result is modified and tested //How do you prevent someone coming after you and adds a `continue` //here which prevents result to be updated in the and of the loop? calculateValue(result); //[2] Duplicated code, see [1] }
可以凝结成:
FooType result; while (calculateValue(result) , result.isBared()) { //all your (possibly numerous) code lines go here }
这样,更新result
的代码只在一个地方,并且在检查其条件的那一行附近。
也许不相关:variables可以通过parameter passing更新的另一个原因是函数需要返回错误代码,除了修改/返回计算的值。 在这种情况下:
ErrorType fallibleCalculation(FooType &result) {/*...*/}
然后
FooType result; ErrorType error; while (error = fallibleCalculation(result) , (Success==error && result.isBared())) { //... }
但正如在评论中指出的那样,你也可以在没有逗号的情况下做到这一点:
FooType result; ErrorType error; while (Success == fallibleCalculation(result) && result.isBared()) { //... }
没有任何。 该代码中的比较是完全多余的。
我的问题是在if
或while
语句中逗号的优点是什么? 为什么允许?
它的存在是因为语句和expression式在C中是不同的东西。复合expression式是一种从理论(和其他一些语言)理解的构造,如果没有以逗号的forms添加它,它将会丢失。 它在声明中的使用是他们为什么需要它的原始理由。
但是,从理论的angular度来看,使语言更加完整,后来发现了没有人计划的用途。 早期的C ++是生成C作为输出的翻译器,并且具有顺序expression式对于允许内联函数在C代码中真正生成“在线”逻辑是绝对必要的。
这包括expression式出现的任何地方, 包括 if
语句的条件。
同样,它已被用在“有趣”的macros中。 就像C ++通过提供内联函数来消除macros一样,迟到的x11编译器发现Boost FOREACH范围循环(最终,仿真x11中添加的语言特性)非常方便,那就是一个与逗号运算符有关的非常聪明的macros。
(嗯,当前的版本使用链接的if
/ else
扩展为多个语句,而不是将它们全部拼凑成一个单一的。)
现在,还有另外一种方法可以将任何语句放入expression式(lambdas)中,所以未来疯狂的模拟更新的语言特性或特定于领域的embedded式语言的macros可能不再需要使用该语言。
所以,不要这样写代码。 除非写出帮助函数或分割成多个语句,这很简单。
但是,对于一个想在一个地方轻松使用的macros而言,这可能只是一件事情,而这个地方就在一个if
或while
。 这可以在C ++源代码中托pipe的特定于领域的语言或者embedded式实时系统中使用的语言仿真function (可能是替代exception处理)来certificate是合理的。
总之,它没有一个正常的使用。 但它是完整的,你永远不知道什么时候有人会发现它有用。