|
|
1
64
C++ standard 1.9.16:
在我看来,这段代码:
完全合法。它将增加
|
|
|
2
14
以 Kristo's answer ,
可能会导致函数调用
或
甚至
运行以下命令查看您的平台上发生了什么:
在我的机器上,我得到
每次,但这段代码 不可移植 ,所以我希望看到不同编译器的不同结果。 |
|
|
3
5
标准规定副作用发生在调用之前,因此代码与以下代码相同:
而不是:
因此,在这种情况下是安全的,因为list.erase()不会使除已擦除的迭代器之外的任何迭代器无效。 也就是说,这是一种糟糕的风格——所有容器的擦除函数都会返回下一个迭代器,所以你不必担心由于重新分配而使迭代器无效,所以惯用代码是这样的:
你也不会在没有警告的情况下编译原始代码——你必须编写
为了避免出现关于未使用回报的警告,这将是一个很大的线索,表明你正在做一些奇怪的事情。 |
|
|
4
3
这完全没问题。 传递的值将是增量前的“i”值。 |
|
|
5
3
C++标准1.9.16对于如何为类实现运算符++(后缀)非常有意义。当调用运算符++(int)方法时,它会自动递增并返回原始值的副本。正如C++规范所说。
然而,我清楚地记得使用旧的(ANSI之前的)C编译器,其中:
这种行为取决于编译器的实现。(让移植变得有趣。) 很容易测试和验证现代编译器现在的行为是否正确:
回复帖子中的评论。..…而且几乎在很大程度上 每个人的 答案。..(谢谢大家!) 我认为我们需要更好地说明这一点: 鉴于:
那么我们不知道是否 g() 将被调用 比前后 h() . 但我们确实知道 两者 g() 和 h() 将在之前调用 baz() . 鉴于:
再一次,我们不知道是哪一个 我++ 将首先进行评估,甚至可能不会 我 将在之前递增一次或两次 被称为。 结果未定义! (给定 i=0 ,这可能是 巴(0,0) 或 巴(1.0) 或 或者真的很奇怪!) 鉴于:
我们现在知道了 我 将在之前递增 foo() 被调用。像 Kristo 指出从 the C++ standard section 1.9.16:
该标准第1.9.16节还列出了(作为示例的一部分):
我们可以用以下方式轻松地证明这一点:
所以,是的, 我 在之前递增 foo() 被调用。 从以下角度来看,这一切都很有意义:
这里 Foo::运算符++(int) 必须在之前调用 delta() 。增量操作必须在调用期间完成。 在我的(也许过于复杂)例子中:
必须执行以获取用于的对象 object.bar(“B”,i++) 等等 C 和 D . 我++ 我 打电话之前 (尽管 bar(“B”,…) 用旧值调用 我 ),因此 我 在之前递增 bar(“C”,i) 和 . 返回 j_random_hacker 的评论:
这个问题比你想象的要复杂得多。.. 将问题改写为代码。..
现在我们只有 表达。根据标准(第8页第1.9节,pdf第20页):
因此,我们可能会认为,由于优先级,我们的表达式将与以下表达式相同:
但是,因为(a^b)^c==a^(b^c)没有任何可能的溢出情况,所以它可以按任何顺序重写。.. 但是,由于bar()正在被调用,并且可能涉及副作用,因此这个表达式不能以任何顺序重写。优先规则仍然适用。 bar() . i+=1 发生?好吧,这还需要以前发生 bar(“B”,…) 被调用。(尽管 用旧值调用。) 所以,它以前肯定会发生 bar(C) 和 bar(D) ,以及之后 bar(A) . 答案:否 。我们总是有“A=0,B=0,C=1,D=1”, 如果编译器符合标准。 但考虑另一个问题:
R的值是多少? 如果 i+=1 j ,我们将得到0^0^1=1。但如果 i+=1 事实上,R是零。这 i+=1 我想这就是原因: i=7,i++,i++;//i变为9(有效)
在每种情况下 我 在每个表达式结束时发生变化。(在计算任何后续表达式之前。) PS:考虑:
i+=1 必须事先进行评估 . 香港高等科技教育学院 R |
|
|
6
1
以MarkusQ的答案为基础:;) 或者更确切地说,比尔对此的评论: 编辑: 啊,评论又消失了。..好吧) 他们是 允许 将同时进行评估。从技术上讲,它是否在实践中发生无关紧要。
事实上,我希望这是一个常见的优化。从指令调度的角度来看。您需要评估以下内容:
但左翼和右翼的论点之间真的没有依赖性。参数求值以未指定的顺序进行,也不需要按顺序进行(这就是为什么函数参数中的new()通常是内存泄漏,即使被包裹在智能指针中) 当你在同一个表达式中两次修改同一个变量时,会发生什么,这也是未定义的。 然而,我们确实在1和2之间以及3和4之间有依赖关系。 那么,编译器为什么要在计算3之前等待2完成呢?这引入了额外的延迟,在4可用之前,需要的时间甚至比必要的时间还要长。 假设每个周期之间有1个周期的延迟,那么从1完成到4的结果准备就绪,我们需要3个周期才能调用函数。 但是,如果我们对它们进行重新排序,并按照1、3、2、4的顺序进行计算,我们可以在2个周期内完成。1和3可以在同一个循环中启动(甚至合并到一条指令中,因为它是同一个表达式),在下面,2和4可以被求值。 |
|
|
7
0
萨特 Guru of the Week #55 (以及“More Exceptional C++”中的相应部分)以一个例子讨论了这个确切的情况。 据他介绍,这是一个完全有效的代码,实际上是一个试图将语句转换为两行的情况: items.erase(i); i++; 做 不 生成语义上与原始语句等效的代码。 |
|
|
8
-1
以蜥蜴比尔的回答为基础:
(这意味着并行评估实际值,然后应用postops)。 --马库斯Q |