逗号在条件语句中的优点是什么
What is the advantage of commas in a conditional statement?
我们可以将if
语句写成
if (a == 5, b == 6, ... , thisMustBeTrue)
并且只有最后一个条件应该满足才能进入CCD_ 2主体。
为什么允许?
稍微更改一下您的示例,假设是这个
if ( a = f(5), b = f(6), ... , thisMustBeTrue(a, b) )
(注意=
而不是==
)。在这种情况下,逗号保证了从左到右的评估顺序。相比之下,有了这个
if ( thisMustBeTrue(f(5), f(6)) )
您不知道CCD_ 5是在CCD_。
更正式地说,逗号允许您编写表达式(a,b,c)
的序列,就像使用;
编写语句序列a; b; c;
一样。正如;
创建一个序列点(完整表达式的末尾)一样,逗号也是如此。只有顺序点决定评估的顺序,请参阅本文。
当然,在这种情况下,你实际上应该写这个
a = f(5);
b = f(6);
if ( thisMustBeTrue(a, b) )
那么,什么时候逗号分隔的表达式序列比;
分隔的语句序列更可取呢?我几乎从来不会说。也许在宏中,当您希望右侧的替换为单个表达式时。
简而言之:尽管这样做是合法的,但在if
或while
语句的条件部分使用逗号运算符通常是没有意义的(编辑:尽管后者有时可能会有所帮助,正如用户5534870在他的回答中所解释的那样)。
更详细的解释:除了语法功能(例如,在初始化器列表、变量声明或函数调用/声明中分离元素)之外,在C和C++中,,
也可以是一个普通的运算符,就像+
一样,因此它可以在任何允许表达式的地方使用(在C++中,你甚至可以重载它)
与大多数其他运算符的不同之处在于,尽管两边都得到了求值,但它不会以任何方式组合左表达式和右表达式的输出,而是只返回右表达式
之所以引入它,是因为有人(可能是Dennis Ritchie)出于某种原因决定,C需要一种语法来在一个位置写两个(或多个)不相关的表达式,而在这个位置上,你通常只能写一个表达式。
现在,if
语句的条件(以及其他条件)就是这样一个地方,因此,您也可以在那里使用,
运算符——这样做是否有意义是一个完全不同的问题!特别是,与例如函数调用或变量声明不同,逗号在那里没有特殊意义,所以它总是这样做:它向左和向右计算表达式,但只返回右表达式的结果,然后由if
语句使用。
我现在唯一能想到的两点是,使用(非重载),
-运算符有意义的地方是:
-
如果您想在
if
0循环的头部增加多个迭代器:for ( ... ; ... ; ++i1, ++i2){ *i2=*i1; }
-
如果要在C++11 constexpr函数中计算多个表达式。
再重复一遍:在if
或while
语句中使用逗号运算符——就像你在例子中展示的那样——是不明智的。这只是C和C++语言语法允许你编写代码的另一个例子,乍一看,它的行为并不像人们所期望的那样。还有很多。。。。
对于if
语句,将某些内容放入逗号表达式而不是外部并没有真正的意义。
对于while
语句,将逗号表达式置于条件中会在进入循环时执行第一部分,在循环时执行或。如果没有代码复制,就无法轻松复制。
那一个do
怎么样。。。while
语句?我们只需要担心循环本身,对吧?事实证明,即使在这里,也不能通过将第一部分移动到循环中来安全地替换逗号表达式。
首先,循环体中变量的析构函数还没有运行,这可能会有所不同。另一方面,循环中的任何continue
语句都将只到达逗号表达式的第一部分,当它确实处于条件中而不是循环体中时。
没有优点:逗号运算符只是一个表达式,其类型为表达式列表中的最后一个表达式的类型,if语句计算布尔表达式。
if(<expr>) { ... }
with type of <expr> boolean
这是一个奇怪的运算符true,但它并没有什么魔力——只是它混淆了函数调用中的表达式列表和参数列表。
foo(<args>)
with <args> := [<expr>[, <expr>]*]
请注意,在参数列表中,逗号与分隔参数的绑定更强。
接下来的内容有点牵强,这取决于你可能想要的狡猾程度
考虑这样一种情况,即函数通过修改通过引用或指针传递的参数来返回值(可能来自设计糟糕的库,或者为了确保该值不会因返回后未赋值而被忽略,不管怎样)。
void calculateValue(FooType &result) {/*...*/}
那么,如何使用依赖于result
的条件语句呢?
您可以声明将要修改的变量,然后用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
的代码只在一个地方,并且在检查其条件的行附近。
可能不相关:变量可以通过参数传递更新的另一个原因是,除了修改/返回计算值外,函数还需要返回错误代码。在这种情况下:
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()) {
//...
}
无任何内容。该代码中对a
的比较是完全多余的。
我的问题是if
或while
语句中逗号的优势是什么?为什么允许
它的存在是因为语句和表达式在C中是不同的东西。复合表达式是一种从理论(和其他一些语言)中理解的结构,如果不以逗号的形式添加它,它就会丢失。它在for
声明中的使用是他们为什么需要它的最初理由
但是,通过从合理的理论角度使语言更加完整,它后来发现了无人计划的用途。早期的C++是一个将C作为输出生成的翻译器,具有顺序表达式对于允许内联函数在C代码中真正生成"内联"逻辑来说是绝对必要的。
包括表达式出现的任何位置,包括if
语句的条件。
同样,它也被用于"有趣"的宏中。正如C++通过提供内联函数来废除宏一样,直到up-to-x11编译器发现Boost FOREACH范围循环(最终,对x11中添加到语言中的功能进行了模拟)非常方便,这是一组非常聪明的宏,涉及逗号运算符。
(嗯,当前版本使用链式if
/else
扩展为多个语句,而不是将其全部填充到单个while
中。)
现在,有另一种方法可以将任何语句放入表达式(lambdas)中,因此,未来疯狂的宏业务可能不需要再使用它了。
所以,不要这样写代码。除非它比编写辅助函数或拆分为多个语句更清楚、更简单。
但是,对于一个宏来说,它可能只是你想在一个地方轻松使用的东西,而这个地方在if
或while
的parens内部。这可以在C++源代码中托管的域特定语言中得到证明,也可以在语言模拟功能(也许)中作为嵌入式实时系统中使用的异常处理的替代方案。
简而言之,它没有一个正常的良好使用。但它是为了完整性而存在的,你永远不知道什么时候会有人觉得它有用。
- "类模板示例<int>;"语句对 C++11 是什么意思?
- 主线的等价语句是什么
- 是什么使这个以'+'开头的字符串添加成为有效的语句?
- 在 if 语句中处理多个 or 的更优雅的方法是什么
- "1L << count"是什么意思?如何使用超出"unsigned long long int? "范围的语句编号打印?
- 学习时空复杂性时语句XYZ的含义是什么?
- C++:无论如何,有什么可以知道是什么触发了 If 语句
- 语句中分配给 num 的值是什么
- for 循环后的分号是什么意思?为什么第一个循环语句中有 j++
- 这个语句到底是什么意思 stack<int, list<int> > 它与 stack 有何不同<int>?
- 打印此矩阵的 if 语句是什么
- 在使用语句中指定类名的内容是什么
- 当我需要添加一个无用的返回语句时,C++约定是什么
- 当C/C++程序切换语句转到未定义的大小写并且缺少默认值时,它的正确行为是什么:
- 下面的C++语句是什么意思
- 查找语句中的"!=vector.end()"是什么意思?
- 切换或 if 语句 - C++中更清楚的是什么
- 开关语句中的逗号运算符是什么意思
- 条件语句在比较表达式时的基础是什么?
- 在下面的C++语句中放置 const 的好地方是什么