C++ 逗号运算符的正确用法是什么?

C++ 逗号运算符的正确用法是什么?,c++,c,coding-style,comma-operator,C++,C,Coding Style,Comma Operator,我看到了这个代码: if (cond) { perror("an error occurred"), exit(1); } 你为什么要那样做?为什么不只是: if (cond) { perror("an error occurred"); exit(1); } 逗号运算符的合法情况很少见,但确实存在。一个例子是,当您希望在条件计算中发生某些事情时。例如: std::wstring example; auto it = example.begin(); while (i

我看到了这个代码:

if (cond) {
    perror("an error occurred"), exit(1);
}
你为什么要那样做?为什么不只是:

if (cond) {
    perror("an error occurred");
    exit(1);
}

逗号运算符的合法情况很少见,但确实存在。一个例子是,当您希望在条件计算中发生某些事情时。例如:

std::wstring example;
auto it = example.begin();
while (it = std::find(it, example.end(), L'\\'), it != example.end())
{
    // Do something to each backslash in `example`
}
a<b?(x=5,b=6,d=i):exit(1);
它也可以用于只能放置一个表达式,但希望发生两件事的地方。例如,以下循环在For循环的第三个组件中递增x,递减y:

int x = 0;
int y = some_number;
for(; x < y; ++x, --y)
{
    // Do something which uses a converging x and y
}
intx=0;
int y=某个_数;
对于(;x

不要去寻找它的用途,但如果它是合适的,不要害怕使用它,如果你看到其他人在使用它,也不要被抛出循环。如果您有两个东西没有理由不作为单独的语句,请将它们作为单独的语句,而不是使用逗号运算符。

在您的示例中,它没有任何理由。当它写为

if(cond)
  perror("an error occured"), exit(1) ;
--那么你就不需要花括号了。但这是一个灾难的邀请

逗号运算符将两个或多个表达式置于引用仅允许一个表达式的位置。在你的情况下,没有必要使用它;在其他情况下,例如在while循环中,它可能很有用:

while (a = b, c < d)
  ...
while(a=b,c

while循环的实际“求值”仅受最后一个表达式的控制。

逗号运算符允许在需要表达式的地方对表达式进行分组

例如,在某些情况下,它可能很有用:

// In a loop
while ( a--, a < d ) ...

文档的链接。

在您的情况下,逗号运算符是无用的,因为它本可以用来避免,但事实并非如此,因为作者已经将它们放在了一起。因此,它是无用的,可能会让人混淆

逗号运算符的主要用途是混淆;它允许做两件事 读者只希望看到的东西。最常见的 用于向条件添加副作用,属于此范围 类别有几个案例可能被认为是有效的, 然而:

在K&R中用来表示它的那个:递增2
循环的
中的变量。在现代代码中,这可能发生在
函数类似于
std::transform
,或
std::copy
,其中输出迭代器 与输入迭代器同步递增。(当然,更常见的情况是 当然,这些函数将包含一个
while
循环,其中 循环结束时在单独语句中的增量 在某些情况下,使用逗号而不是两个语句是没有意义的。)

另一种情况是输入参数的数据验证 在初始值设定项列表中:

MyClass::MyClass( T const& param )
    : member( (validate( param ), param) )
{
}
(这假设
validate(param)
将在以下情况下引发异常: 有点不对劲。)这种用法并不特别吸引人,尤其是 因为它需要额外的括号,但是没有太多的选择

最后,我有时会看到会议:

ScopedLock( myMutex ), protectedFunction();
,从而避免了为
ScopedLock
发明名称。说 事实上,我不喜欢它,但我已经看到它的使用,和替代品 添加额外的大括号以确保
ScopedLock
立即
destructed也不是很漂亮。

举一些例子可以更好地理解这一点:

第一名: 考虑一个表达式:

   x = ++j;
但就目前而言,如果我们需要分配一个临时调试值,那么我们可以编写

   x = DEBUG_VALUE, ++j; 
秒:
逗号
运算符常用于
for()
-循环,例如:

for(i = 0, j = 10; i < N; j--, i++) 
 //      ^                   ^     here we can't use ;  
它也可以在一个步骤中完成

  if(x = n / d, n % d) // == x = n / d; if(n % d)
    printf("Remainder not zero, x + 1 = %d", (x + 1));
  else
    printf("Remainder is zero,  x - 1 = %d", (x - 1));
PS:知道有时使用
运算符会带来灾难性后果也可能会很有趣。例如,在问题中,OP错误地忘记了写函数的名称,而不是写
tokens=strtok(NULL,“,”),他写了
tokens=(NULL,“,”)并且他没有得到编译错误——但这是一个有效的表达式,
tokens=“,”在他的程序中引起了无限循环

运算符()的实际用途似乎很少

Bjarne Stroustrup,C语言的设计与发展++

逗号的大部分常用用法可以在维基百科的文章中找到

我在使用时发现了一个有趣的用法,它明智地重载了运算符,使其表现为逗号分隔的值列表,可以将其推送到向量对象的末尾

#include <boost/assign/std/vector.hpp> // for 'operator+=()'
using namespace std;
using namespace boost::assign; // bring 'operator+=()' into scope

{
    vector<int> values;  
    values += 1,2,3,4,5,6,7,8,9; // insert values at the end of the container
}
#包括//for'operator+=()'
使用名称空间std;
使用名称空间boost::assign;//将“运算符+=()”引入范围
{
向量值;
values+=1,2,3,4,5,6,7,8,9;//在容器末尾插入值
}
不幸的是,一旦编译器开始支持,上述用于原型设计的用法现在看起来已经过时了

这就让我们回到过去

运算符()的实际用途似乎很少

Bjarne Stroustrup,C语言的设计与发展++


boost::assign
重载逗号运算符以实现这种语法:

vector<int> v; 
v += 1,2,3,4,5,6,7,8,9;
向量v; v+=1,2,3,4,5,6,7,8,9;
如果您想在条件为truefalse时执行两条或多条指令,则行程操作员可以使用该选项。但是请记住,返回值将是最右的表达式,这是由于逗号运算符从左到右求值规则(我是指括号内)

例如:

std::wstring example;
auto it = example.begin();
while (it = std::find(it, example.end(), L'\\'), it != example.end())
{
    // Do something to each backslash in `example`
}
a<b?(x=5,b=6,d=i):exit(1);

A逗号运算符在表达式SFINAE之外是无用的。逗号运算符有时在诸如宏体这样的上下文中很有用,在宏体中,您希望将多个操作组合成一个语句。否则,在循环中增加两个变量时,或者在其他一些样式化变量中,它可能会很有用