cout << a++ << a; 的正确答案是什么?
What is the correct answer for cout << a++ << a;?
最近在一次采访中,有一个客观类型的问题。
int a = 0;
cout << a++ << a;
答案:
一. 10
b. 01
C. 未定义的行为
我回答了选项 b,即输出将是"01"。
但令我惊讶的是,后来一位面试官告诉我,正确的答案是选项c:未定义。
现在,我确实知道C++中序列点的概念。以下语句的行为未定义:
int i = 0;
i += i++ + i++;
但根据我对cout << a++ << a
语句的理解,ostream.operator<<()
将被调用两次,首先是ostream.operator<<(a++)
,后来是ostream.operator<<(a)
。
我还在VS2010编译器上检查了结果,其输出也是"01"。
你可以想到:
cout << a++ << a;
如:
std::operator<<(std::operator<<(std::cout, a++), a);
C++保证先前评估的所有副作用都将在序列点进行。函数参数计算之间没有序列点,这意味着参数a
可以在参数std::operator<<(std::cout, a++)
之前或之后进行计算。所以上述结果是不确定的。
C++17更新
在C++17中,规则已更新。特别:
在移位运算符表达式
E1<<E2
和E1>>E2
中,E1
的每个值计算和副作用都先于E2
的每个值计算和副作用进行排序。
这意味着它需要代码产生结果b
,输出01
。
有关更多详细信息P0145R3请参阅优化惯用C++表达式求值顺序。
从技术上讲,总的来说,这是未定义的行为。
但是,答案有两个重要方面。
代码语句:
std::cout << a++ << a;
评估为:
std::operator<<(std::operator<<(std::cout, a++), a);
该标准没有定义函数参数的计算顺序。
因此,请执行以下任一操作:
- 首先评估
std::operator<<(std::cout, a++)
或 - 首先评估
a
或 - 它可以是任何实现定义的顺序。
根据标准,此顺序是未指定的[参考文献 1]。
[参考文献 1]C++03 5.2.2 函数调用
第8段
参数的计算顺序未指定。参数表达式计算的所有副作用在输入函数之前生效。未指定后缀表达式和参数表达式列表的计算顺序。
此外,函数的参数计算之间没有序列点,但只有在计算所有参数之后才存在序列点[Ref 2]。
[参考文献 2]C++03 1.9 程序执行 [介绍执行]:
第17段:
调用函数时(无论函数是否内联),在计算所有函数参数(如果有)之后,在执行函数体中的任何表达式或语句之前,都会有一个序列点。
请注意,这里c
的值在没有干预序列点的情况下被多次访问,关于这一点,标准说:
[参考文献 3]C++03 5 表达式 [expr]:
第4段:
....
在上一个和下一个序列点之间,标量对象的存储值应通过表达式的计算最多修改一次。此外,访问先前的值只能用于确定要存储的值。对于完整表达式的子表达式的每个允许顺序,应满足本款的要求 表达;否则,行为是未定义的。
该代码在不干预序列点的情况下多次修改c
,并且不会访问它来确定存储对象的值。这显然违反了上述条款,因此标准规定的结果是未定义的行为[参考文献3]。
序列点仅定义部分排序。 在您的情况下,您有(完成过载解决后):
std::cout.operator<<( a++ ).operator<<( a );
a++
和第一次调用之间有一个序列点 std::ostream::operator<<
,并且第二次a
和第二次呼叫std::ostream::operator<<
,但那里a++
和 a
之间没有序列点;唯一的订单限制因素是a++
进行全面评估(包括副作用)在第一次调用operator<<
之前,并且第二次a
完全在第二次调用 operator<<
之前进行了评估。 (也有顺序约束:第二次调用operator<<
不能在第一个之前,因为它需要第一个的结果作为参数。 §5/4 (C++03) 规定:
除非另有说明,否则计算单个运算符的操作数和子表达式个体表达,以及副作用发生的顺序,未指定。 在上一个和下一个序列点之间一个标量对象应最多修改一次其存储值表达式的计算。此外,先验值应为仅访问以确定要存储的值。 的要求对于完整表达式的子表达式;否则行为为定义。
表达式的允许排序之一是 a++
, a
, 首先呼叫operator<<
,第二次呼叫operator<<
;这将修改a
(a++
)的存储值,并访问它,而不是确定新值(第二个a
),行为未定义。
正确答案是质疑问题。这种说法是不可接受的,因为读者看不到明确的答案。另一种看待它的方法是,我们引入了副作用(c ++),使语句更难解释。简洁的代码很棒,只要它的含义是明确的。
- 欧拉项目#8答案是大以获得有效答案
- 请解释这句话(cout<<1+int((a<b)^((b-a)&1) )<<endl
- 首要问题的答案让值班员搞错了
- 呼叫运营商<<临时
- C++问题:用户认为数字1-100,程序提出问题不超过6次即可得到答案。无法正确
- 如何防止clang格式在流运算符调用之间添加换行符<<
- <<操作员在下面的行中工作
- 我试图制作一个程序,要求用户输入问题和答案,但程序循环不正确
- 使用 bfs 解决连接组件问题时得到错误的答案
- 同一对象的"sizeof"的不同答案
- 递归求和任务的错误答案
- 我无法在Visual Studio代码中使用CIN输入答案,它说输入您的年龄,但它说只读文本编辑器如何解决这个问题?
- 为什么C++程序在太大时返回代码而不是答案?
- 不理解为什么代码没有产生所需的答案
- 为什么我在代码厨师的 CMPRSS 问题中得到 WA(错误答案)?
- 我的程序将 26 个字母转换为 ascII 没有显示正确答案
- 请找出我的代码中的错误,它在提交得到错误答案的同时仍然适用于我的所有测试用例
- 任何人都可以弄清楚这段代码如何显示运行错误?它打印无限时间 -1 以及正确答案
- C++ 中 pow() 函数的输出没有给出准确的答案
- 函数从指针 c++ 中获取错误的值并返回错误的答案