逗号运算符如何在C++中工作?
例如,如果我这样做:
a = b, c;
最终是否等于b或c?
(是的,我知道这很容易测试 - 只是在这里记录,以便有人快速找到答案.)
更新: 此问题在使用逗号运算符时暴露了细微差别.只是记录下来:
a = b, c; // a is set to the value of b! a = (b, c); // a is set to the value of c!
这个问题实际上是受到代码中的拼写错误的启发.打算做什么
a = b; c = d;
转换成
a = b, // <- Note comma typo! c = d;
Konrad Rudol.. 127
请注意,逗号运算符可能在C++中过载.因此,实际行为可能与预期的行为非常不同.
例如,Boost.Spirit非常巧妙地使用逗号运算符来实现符号表的列表初始值设定项.因此,它使以下语法成为可能且有意义:
keywords = "and", "or", "not", "xor";
请注意,由于运算符优先级,代码(故意!)相同
(((keywords = "and"), "or"), "not"), "xor";
也就是说,第一个被调用的运算符是keywords.operator =("and")
返回一个代理对象,在该代理对象上operator,
调用其余的s:
keywords.operator =("and").operator ,("or").operator ,("not").operator ,("xor");
@Jeff恰恰相反.在列表周围有一个括号,这不起作用,因为编译器只看到两个`char []`之间的逗号运算符,它不能重载.代码*故意*先为每个剩余元素调用`operator =`然后调用`operator,`. (17认同)
efotinis.. 122
逗号运算符具有所有C/C++运算符的最低优先级.因此,它始终是绑定到表达式的最后一个,这意味着:
a = b, c;
相当于:
(a = b), c;
另一个有趣的事实是逗号运算符引入了一个序列点.这意味着表达式:
a+b, c(), d
保证按顺序评估其三个子表达式(a + b,c()和d).如果它们有副作用,这是很重要的.通常,编译器可以按照他们认为合适的顺序评估子表达式; 例如,在函数调用中:
someFunc(arg1, arg2, arg3)
可以按任意顺序评估参数.请注意,函数调用中的逗号不是运算符; 他们是分隔符.
请注意,逗号运算符可能在C++中过载.因此,实际行为可能与预期的行为非常不同.
例如,Boost.Spirit非常巧妙地使用逗号运算符来实现符号表的列表初始值设定项.因此,它使以下语法成为可能且有意义:
keywords = "and", "or", "not", "xor";
请注意,由于运算符优先级,代码(故意!)相同
(((keywords = "and"), "or"), "not"), "xor";
也就是说,第一个被调用的运算符是keywords.operator =("and")
返回一个代理对象,在该代理对象上operator,
调用其余的s:
keywords.operator =("and").operator ,("or").operator ,("not").operator ,("xor");
逗号运算符具有所有C/C++运算符的最低优先级.因此,它始终是绑定到表达式的最后一个,这意味着:
a = b, c;
相当于:
(a = b), c;
另一个有趣的事实是逗号运算符引入了一个序列点.这意味着表达式:
a+b, c(), d
保证按顺序评估其三个子表达式(a + b,c()和d).如果它们有副作用,这是很重要的.通常,编译器可以按照他们认为合适的顺序评估子表达式; 例如,在函数调用中:
someFunc(arg1, arg2, arg3)
可以按任意顺序评估参数.请注意,函数调用中的逗号不是运算符; 他们是分隔符.
它等于b
.
逗号运算符的优先级低于赋值.
逗号运算符:
优先级最低
是左联想的
为所有类型(内置和自定义)定义了默认版本的逗号运算符,它的工作方式如下 - 给定exprA , exprB
:
exprA
被评估
结果exprA
被忽略了
exprB
被评估
的结果exprB
被返回作为整个表达式的结果
对于大多数运算符,允许编译器选择执行顺序,如果它不影响最终结果,甚至需要跳过执行(例如,false && foo()
将跳过调用foo
).然而,这不是逗号运算符的情况,并且上述步骤将始终发生*.
实际上,默认的逗号运算符的工作方式与分号几乎相同.不同之处在于,由分号分隔的两个表达式形成两个单独的语句,而逗号分隔将所有表达式保留为单个表达式.这就是为什么逗号运算符有时用于以下场景:
C语法需要单个表达式,而不是语句.例如inif( HERE )
C语法需要单个语句,而不是更多,例如在for
循环的初始化中for ( HERE ; ; )
当你想跳过花括号并保持一个声明:( if (foo) HERE ;
请不要这样做,它真的很丑!)
如果语句不是表达式,则分号不能用逗号替换.例如,这些是不允许的:
(foo, if (foo) bar)
(if
不是表达)
int x,int y(变量声明不是表达式)
在您的情况下,我们有:
a=b, c;
,相当于a=b; c;
,假设该a
类型不会使逗号运算符超载.
a = b, c = d;
相当于a=b; c=d;
,假设该a
类型不会使逗号运算符重载.
请注意,并非每个逗号实际上都是逗号运算符.一些逗号含义完全不同:
int a, b;
---变量声明列表以逗号分隔,但这些不是逗号运算符
int a=5, b=3;
---这也是一个逗号分隔的变量声明列表
foo(x,y)
---以逗号分隔的参数列表.事实上,x
并且y
可以在被评估的任何命令!
FOO(x,y)
---逗号分隔的宏参数列表
int foo(int a, int b)
---逗号分隔的参数列表
Foo::Foo() : a(5), b(3) {}
---类构造函数中的逗号分隔的初始化列表
*如果您应用优化,则不完全正确.如果编译器认识到某段代码对其余代码完全没有影响,它将删除不必要的语句.
进一步阅读:http://en.wikipedia.org/wiki/Comma_operator
值a
将是b
,但表达式的值将是c
.也就是说,在
d = (a = b, c);
a等于b
,d
等于c
.
b的值将被分配给a.什么都不会发生在c