C++中的边际效应(Side Effect)与顺序点(Sequence Point)问题

 转自水木BBS

 

 

副作用真是一个很头痛的问题。初学者头痛是因为它令人迷惑,老鸟头痛是因为它会冷不

防叮你一口,只要你稍微粗心一点。当然,老碰到问这样问题的人也让人头痛。

 

为了理解副作用带来的困难,必须要理解C++中的时序点(Sequence Point)的概念。根据I

SO14882:1998中1.9节第7款的叙述,时序点是前一求值中所有副作用已经结束而下一求值

中任何副作用尚未开始的地方。具体地说,有下面四个地方:

1. 在每一个非子表达式结束的地方。用ISO14882中的术语,就是完全表达式(full-expre

ssion)结束的地方。比如一条表达式语句,函数调用的一个完整参数,if语句里的条件表

达式等等;

2. 在一个函数所有参数求值完以后并且在准备调用该函数之前;

3. 当一个函数返回的时候:就是在返回值已经被复制以后,而在运行该函数的任何外部之

前;

4. 在下列表达式中的第一个表达式之后,假设这里用的都是内置的运算符而没有被重载:

 

   //      expr1 && expr2

   //      expr1 || expr2

   //      expr1 ? expr2 : expr3

   //      expr1, expr2

 

理解了时序点的概念以后,其他的问题就迎刃而解了。C++里说的是,如果在两个时序点之

间有两个或者多个副作用,那么这些副作用的时序是不定的。如果表达式的值依赖于这些

副作用间的顺序,那么表达式的值也就是不定的。

 

i=i++;显然就属于这种情况,如果i这里是基本类型的话。而在c.erase(i++)就是另外一种

情况,因为在i++之后调用c.erase之前是有一个时序点的。因此就没有二义性问题。

==============NB的分割线================

说实话,偶看不懂原文的意思,里面有好多怪异的词,譬如“副作用”,“非子表达式”,另外还有一些表达感觉有点蹩脚。可能是偶智商实在太低。

找了几篇更”专业“一点的文章,这里的“副作用”应该就是"Side Effect",个人觉得还是翻译成“边际效应”更贴切一些。

一些关于Side effect和Sequence point文章:

http://en.wikipedia.org/wiki/Sequence_point 其实还是wiki上写的明白。

http://learn.akae.cn/media/ch16s03.html  这差不多是wiki的翻译版,也不错。