C++ cout<;的正确答案是什么&书信电报;a和x2B+<&书信电报;A.

C++ cout<;的正确答案是什么&书信电报;a和x2B+<&书信电报;A.,c++,c++-faq,C++,C++ Faq,最近在一次采访中,有一个客观类型的问题 int a = 0; cout << a++ << a; 但根据我对声明cout的理解,从技术上讲,这是未定义的行为 但是,答案有两个重要方面 守则声明: std::cout << a++ << a; std::cout你可以想到: cout << a++ << a; 序列点只能定义偏序。就你而言,你有 (过载解决完成后): std::cout.operator正确答案是提问。这

最近在一次采访中,有一个客观类型的问题

int a = 0;
cout << a++ << a;

但根据我对声明
cout的理解,从技术上讲,这是未定义的行为

但是,答案有两个重要方面

守则声明:

std::cout << a++ << a;
std::cout你可以想到:

cout << a++ << a;

序列点只能定义偏序。就你而言,你有 (过载解决完成后):



std::cout.operator正确答案是提问。这种说法是不可接受的,因为读者看不到明确的答案。从另一个角度来看,我们引入了副作用(c++),使语句更难解释。简洁的代码很好,只要它的含义清楚。

您要求解释吗?我经常面试潜在的候选人,并且对接受问题很感兴趣,这显示了我的兴趣。@jrok这是一种未定义的行为。实现所做的任何事情(包括以你的名义向你的老板发送侮辱性的电子邮件)都是一致的。这个问题迫切需要一个C++11(当前版本的C++)的答案,这个答案没有提到序列点。不幸的是,我对C++11中序列点的替换了解不够。如果不是未定义,它肯定不会是
10
,它可能是
01
00
。(
c++
将始终计算为递增之前的值
c
had)。即使它不是未定义的,它仍然会令人非常困惑。你知道,当我读到标题时“难道我的意思是,
c
只被修改一次,这样程序就可以合法地打印01或10,但不会做一些奇怪的事情。我的理解正确吗?从技术上讲,行为是未定义的,因为有一个对象的修改,并且在没有插入序列点的情况下访问它。未定义不是未指定的;它离开imple心理状态更大的回旋余地。@Als是的。我没有看到你的编辑(尽管我对jrok的声明做出了反应,该程序不能做奇怪的事情——它可以)你编辑的版本是很好的,但在我看来,关键词是偏序;序列点只介绍一个部分排序。新的C++ 0x标准基本上是相同的,但在不同的部分和不同的措辞:)(1.9程序执行[执行],PAR 15):“如果一个标量对象上的副作用相对于同一标量对象上的另一个副作用或使用同一标量对象的值进行的值计算是不排序的,则该行为是不确定的。”我相信这个答案中存在错误标准::cout@Maxim:谢谢你的解释。对于你解释的电话,这将是未定义的行为。但现在,我还有一个问题(可能是更愚蠢的问题,我遗漏了一些基本的东西并大声思考)你是如何推断std的全球版本的:operator@Maxim这并不是说它有什么不同,而是因为
c
有type
int
,所以
operator@pravs是否在C++标准中不再使用“代码>操作程序”序列点,它是不精确的,并已被“在排序后的顺序/顺序”所取代。在。
上,因此上述结果未定义。
您的解释仅适用于未指定,而不适用于未定义。JamesKanze解释了它是如何使未定义变得更糟糕的。这个问题可能表现出糟糕的编程实践(甚至是无效的C++).但答案应该回答问题,指出问题的原因和原因。即使问题的注释完全有效,也不是答案。充其量,这可能是一个注释,而不是答案。从您引用的标准中可以看出一个问题。“除非另有说明”,IIRC,在处理重载运算符时包含一个异常,该异常将运算符视为函数,因此在对std::ostream:的第一次和第二次调用之间创建一个序列点:operator@ChristopherSmith重载运算符的行为类似于函数调用。如果
c
是具有用户定义的
++,而不是
int
,结果将是未指定的,但不会有未定义的行为。@Christophermith在
foo(foo(bar(c)),c中,你在哪里看到两个
c
之间的序列点
?函数调用和返回时都有一个序列点,但在两个
c
@christophermith的求值之间不需要函数调用。如果
c
是UDT,重载运算符将是函数调用,并将引入一个序列点,因此行为不会未定义。B但是子表达式
c
是在
c++
之前还是之后求值的,这仍然是未知数,因此不会指定是否得到递增版本(理论上,每次都不必相同).@Christophermith序列点之前的所有内容都将发生在序列点之后的任何内容之前。但是序列点只定义了一个偏序。例如,在所讨论的表达式中,子表达式
c
c++
之间没有序列点,因此这两者可能以任何顺序出现。至于半序lons…只要它们是完整表达式,它们只会导致一个序列点。其他重要的序列点是函数调用:
f(c++)
将在
f
中看到递增的
c
,逗号运算符,
&
|
也会导致序列点。
std::operator<<(std::operator<<(std::cout, a++), a);
cout << a++ << a;
std::operator<<(std::operator<<(std::cout, a++), a);
std::cout.operator<<( a++ ).operator<<( a );