为什么这些示例之一是未定义的行为,而另一个不是?

Alw*_*ing 4 c++ undefined-behavior

回复的注释指出,不应使用以下代码,因为它表现出未定义的行为:

int old = (std::cin >> old, old);
Run Code Online (Sandbox Code Playgroud)

类似的代码在这里也受到极大的嘲笑,尤其是对于表现出未定义的行为。

另一方面,这个极受好评的答复建议使用以下代码作为逗号运算符的有用性示例:

while (cin >> str, str != "STOP") {
    //process str
}
Run Code Online (Sandbox Code Playgroud)

我假设如果此代码表现出未定义的行为,则不会被投票。

问题:如果第一个代码是未定义的行为(大概是由于使用了读取结果cin而不检查后者的状态),那么第二个代码为什么没问题?

编辑:第一个示例的评论部分中回答了该问题。第二个示例未显示的是它str的一个实例,std::string因此已初始化。因此,没有未定义的行为。

Bat*_*eba 5

int old = (std::cin >> old, old);自C ++ 11起,该语句定义良好,并假定读取了非空白字符。这是因为old如果std::cin在这种情况下失败,则将其设置为零。使用表达式分隔符运算符,也是合法的,因为它对表达式std::cin >> old和进行排序old。如果没有非空白字符被反击,那么old仍然不会被更改,std::cin >> old并且代码的行为是不确定的。

假设str是一种std::string类型,(cin >> str, str != "STOP")则总是定义明确的。如果cin >> str失败,str则保留的初始值(可能是默认构造的),然后再次,对表达式进行排序。

  • “如果std :: cin失败,则将old设置为零。”是不正确的。如果读取了非空白字符,但无法将其转换为int,则将其设置为零。如果无法提取非空白字符,则将其保留不变。 (2认同)
  • 直到哨兵对象成功完成才开始“提取”。请参阅第1-4页的“行为为FormattedInputFunction。” **构造并检查了哨兵对象之后**,该对象可能会跳过前导空格,**通过调用std :: num_get :: get()提取整数值。 )”。您可以检查标准(istream.formatted)作为更详细和权威的参考。 (2认同)