C++11以前的序列点

首先看wiki:
https://en.wikipedia.org/wiki/Sequence_point

简单翻译:

C和C++中的序列点

在C和C++中,下列位置被认为是序列点。(注意,被重载的运算符,相当于函数调用,它们引入的序列点与运算符没有关系,而与函数调用一致)
1.&&(与)、||(或)运算符的左右两边之间有序列点。(为了实现短路逻辑)逗号表达式也是一个序列点。例如, *p++ != 0 && *q++ != 0, *p++!=0这个子表达式的所有副作用完成之后,才会对q进行计算。
2.问号运算符的第一个判断表达式之后,和第二个或者第三个语句之间。例如, a+(*p++)?(*p++):0,在第一个*p++之后有序列点,所以当执行第二个*p++时,第一个自增操作已经完成。
3.在所有的“全表达式”之后。包括表达式语句,如a=b;,和返回值语句,if,switch,while,do-while的控制表达式,以及for循环里的3个语句。
4.调用函数之前。但函数中多个参数表达式的执行顺序是未定义的,不过它们在进入函数调用栈之前肯定全部执行完了。在f(i++) + g(j++) + h(k++)中,f有个参数i,i在进入函数f之前已经自增完成。类似地,j和k也是同样。但是,f、g、h 3个函数调用以什么顺序发生,则是未定义的。导致i、j、k以什么顺序自增也变成未定义了。在函数f执行的时候,j和k可能已经自增,也可能没有。注意,f(a,b,c)中,逗号不是逗号表达式,只是参数的分隔符,因此a、b、c3个表达式的执行顺序是未定的。
5.函数返回,当返回值拷贝到调用栈后。(在C++标准中明确规定,在C中则只是隐含推论出的,未明确规定)
6.初始化结束知乎。如int a = 5;
7.多个声明。如int x=a++,y=a++;,这跟逗号表达式不一样,但也是序列点。
8.在I/O格式化中。例如,在printf(”foo %n %d”, &a, 42);在%n求值以后,尚未打印42之前,有一个序列点。

特别注意:
* f(i++) + g(j++) + h(k++) 三个函数执行顺序未定义
* printf(“%d, %d, %d”, a++, –b, a++), 3个参数表达式执行顺序未定义
* cout << a++ << b++ << c++; 3个表达式的顺序也未定义。因为相当于cout.operator<<(a++). operator<<(b++). operator<<(c++),又相当于operator<<( operator<<( operator<<(cout, a++), b++), c++),<<相当于两个参数的函数。
典型的未定义行为:
Undefined behavior
1) If a side effect on a scalar object is unsequenced relative to another side effect on the same scalar object, the behavior is undefined.两个序列点之间,对同一个变量只能写一次。多次修改会导致未定义行为。
i = ++i + i++; // undefined behavior
i = i++ + 1; // undefined behavior
f(++i, ++i); // undefined behavior
f(i = -1, i = -1); // undefined behavior
2) If a side effect on a scalar object is unsequenced relative to a value computation using the value of the same scalar object, the behavior is undefined.两个序列点之间,对同一个变量又读又写,那么也是未定义的。因为不知道读先发生还是写先发生。
f(i, i++); // undefined behavior
a[i] = i++; // undefined bevahior

在单例模式的double check locking中,之所以会出错,就是因为p = new T;这个语句结束时有个序列点,但未结束之前,赋值和构造谁先发生,就是未定义的了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值