egmkang 服务端开发工程师

sequence point

2014-12-07

如果有好好学习C/C++的话. 应该知道Sequence Point这个东西. 应该也被这个东西坑过. 简单的来讲, C++里面, 一个表达式的子表达式何时求值, 这个C++标准是没有规定的! 所以你不管什么时候求值, 都是符合标准的.

但是如果你的程序, 对表达式的求值有一定的顺序要求, 那么, 呵呵!!! 只能手动拆开.

这几天在看CppCon2014的ppt, 挺好看的. 有很多很有意思的事情. 本文讲The New Old Thing这个PPT里面提到的问题.

先来看一段程序, 需要用c++1y的编译器编译:

#include <iostream>

auto list = [](auto... v) { return [=](auto access) { return access(v...); }; };
auto map = [](auto func) {
     return [=](auto ...z) {
             return list(func(z)...);
                };
};
auto print = [](auto v){
     std::cout << v; return v;
};
int main(){
     list(1, 2, 3, 4)(map(print));
     return 0;
}

这个代码很有意思, 就是为了构造一个list(print(z1), print(z2), print(z3), print(z4)). 但是这个print(z1)恰恰是list表达式里面的一个子表达式…..然后作者就被坑了. 有一些编译器会输出1234, 有一些编译器会输出4321….

那个作者表示非常愤慨, 强烈要求把Sequence Point这种东西改成从左到右的, 而不是任何一种顺序都是合法的. 不过这个想法确实不错, 就是不知道标准委员会的人会不会同意.

PS: 肯定有一些人分不清Sequence Point和函数调用参数push的顺序之间的关系, 我只想说, 表达式求值之后的值, 会按照调用参数push的顺序push. 但是表达式求值的顺序, 和push的顺序, 是两码事情.


Comments